diff --git a/src/client.rs b/src/client.rs index d9e193b9..c3110891 100644 --- a/src/client.rs +++ b/src/client.rs @@ -17,6 +17,7 @@ use super::model::*; use super::oauth2::{Credentials, OAuth, Token}; use super::pagination::{paginate, Paginator}; use crate::model::idtypes::{IdType, PlayContextIdType}; +use std::collections::HashMap; /// Possible errors returned from the `rspotify` client. #[derive(Debug, Error)] @@ -184,8 +185,8 @@ impl Spotify { let ids = join_ids(track_ids); let mut params = Query::new(); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let url = format!("tracks/?ids={}", ids); @@ -245,17 +246,19 @@ impl Spotify { offset: Option, ) -> ClientResult> { let mut params = Query::new(); - if let Some(limit) = limit { - params.insert("limit".to_owned(), limit.to_string()); + let limit = limit.map(|x| x.to_string()); + if let Some(ref limit) = limit { + params.insert("limit", limit); } - if let Some(album_type) = album_type { - params.insert("album_type".to_owned(), album_type.to_string()); + if let Some(ref album_type) = album_type { + params.insert("album_type", album_type.as_ref()); } - if let Some(offset) = offset { - params.insert("offset".to_owned(), offset.to_string()); + let offset = offset.map(|x| x.to_string()); + if let Some(ref offset) = offset { + params.insert("offset", offset); } - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let url = format!("artists/{}/albums", artist_id.id()); let result = self.endpoint_get(&url, ¶ms).await?; @@ -278,7 +281,7 @@ impl Spotify { ) -> ClientResult> { let mut params = Query::with_capacity(1); - params.insert("market".to_owned(), market.to_string()); + params.insert("market", market.as_ref()); let url = format!("artists/{}/top-tracks", artist_id.id()); let result = self.endpoint_get(&url, ¶ms).await?; @@ -361,15 +364,17 @@ impl Spotify { include_external: Option, ) -> ClientResult { let mut params = Query::with_capacity(4); - params.insert("limit".to_owned(), limit.into().unwrap_or(10).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - params.insert("q".to_owned(), q.to_owned()); - params.insert("type".to_owned(), _type.to_string()); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + let limit = limit.into().unwrap_or(10).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); + params.insert("q", q); + params.insert("type", _type.as_ref()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } - if let Some(include_external) = include_external { - params.insert("include_external".to_owned(), include_external.to_string()); + if let Some(ref include_external) = include_external { + params.insert("include_external", include_external.as_ref()); } let result = self.endpoint_get("search", ¶ms).await?; @@ -392,8 +397,10 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(50).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); + let limit = limit.into().unwrap_or(50).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); let url = format!("albums/{}/tracks", album_id.id()); let result = self.endpoint_get(&url, ¶ms).await?; self.convert_result(&result) @@ -428,10 +435,10 @@ impl Spotify { ) -> ClientResult { let mut params = Query::new(); if let Some(fields) = fields { - params.insert("fields".to_owned(), fields.to_owned()); + params.insert("fields", fields); } - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let url = format!("playlists/{}", playlist_id.id()); @@ -453,8 +460,10 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(50).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); + let limit = limit.into().unwrap_or(50).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); let result = self.endpoint_get("me/playlists", ¶ms).await?; self.convert_result(&result) @@ -476,8 +485,10 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(50).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); + let limit = limit.into().unwrap_or(50).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); let url = format!("users/{}/playlists", user_id.id()); let result = self.endpoint_get(&url, ¶ms).await?; self.convert_result(&result) @@ -500,7 +511,7 @@ impl Spotify { ) -> ClientResult { let mut params = Query::new(); if let Some(fields) = fields { - params.insert("fields".to_owned(), fields.to_string()); + params.insert("fields", fields); } match playlist_id { Some(playlist_id) => { @@ -536,13 +547,15 @@ impl Spotify { market: Option, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(50).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + let limit = limit.into().unwrap_or(50).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } if let Some(fields) = fields { - params.insert("fields".to_owned(), fields.to_owned()); + params.insert("fields", fields); } let url = format!("playlists/{}/tracks", playlist_id.id()); let result = self.endpoint_get(&url, ¶ms).await?; @@ -906,8 +919,10 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); let result = self.endpoint_get("me/albums", ¶ms).await?; self.convert_result(&result) } @@ -931,8 +946,10 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); let result = self.endpoint_get("me/tracks", ¶ms).await?; self.convert_result(&result) } @@ -960,10 +977,11 @@ impl Spotify { after: Option, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("type".to_owned(), Type::Artist.to_string()); - if let Some(after) = after { - params.insert("after".to_owned(), after); + let limit = limit.into().unwrap_or(20).to_string(); + params.insert("limit", &limit); + params.insert("type", Type::Artist.as_ref()); + if let Some(ref after) = after { + params.insert("after", &after); } let result = self.endpoint_get("me/following", ¶ms).await?; @@ -1042,15 +1060,12 @@ impl Spotify { time_range: T, ) -> ClientResult> { let mut params = Query::with_capacity(3); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - params.insert( - "time_range".to_owned(), - time_range - .into() - .unwrap_or(TimeRange::MediumTerm) - .to_string(), - ); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + let time_range = time_range.into().unwrap_or(TimeRange::MediumTerm); + params.insert("limit", &limit); + params.insert("offset", &offset); + params.insert("time_range", time_range.as_ref()); let result = self.endpoint_get(&"me/top/artists", ¶ms).await?; self.convert_result(&result) } @@ -1075,15 +1090,12 @@ impl Spotify { time_range: T, ) -> ClientResult> { let mut params = Query::with_capacity(3); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - params.insert( - "time_range".to_owned(), - time_range - .into() - .unwrap_or(TimeRange::MediumTerm) - .to_string(), - ); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + let time_range = time_range.into().unwrap_or(TimeRange::MediumTerm); + params.insert("limit", &limit); + params.insert("offset", &offset); + params.insert("time_range", time_range.as_ref()); let result = self.endpoint_get("me/top/tracks", ¶ms).await?; self.convert_result(&result) } @@ -1100,7 +1112,8 @@ impl Spotify { limit: L, ) -> ClientResult> { let mut params = Query::with_capacity(1); - params.insert("limit".to_owned(), limit.into().unwrap_or(50).to_string()); + let limit = limit.into().unwrap_or(50).to_string(); + params.insert("limit", &limit); let result = self .endpoint_get("me/player/recently-played", ¶ms) .await?; @@ -1273,16 +1286,19 @@ impl Spotify { offset: O, ) -> ClientResult { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - if let Some(locale) = locale { - params.insert("locale".to_owned(), locale); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); + if let Some(ref locale) = locale { + params.insert("locale", locale); } - if let Some(market) = country { - params.insert("country".to_owned(), market.to_string()); + if let Some(ref market) = country { + params.insert("country", market.as_ref()); } - if let Some(timestamp) = timestamp { - params.insert("timestamp".to_owned(), timestamp.to_rfc3339()); + let timestamp = timestamp.map(|x| x.to_rfc3339()); + if let Some(ref timestamp) = timestamp { + params.insert("timestamp", timestamp); } let result = self .endpoint_get("browse/featured-playlists", ¶ms) @@ -1308,10 +1324,12 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - if let Some(market) = country { - params.insert("country".to_owned(), market.to_string()); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); + if let Some(ref market) = country { + params.insert("country", market.as_ref()); } let result = self.endpoint_get("browse/new-releases", ¶ms).await?; @@ -1340,13 +1358,15 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - if let Some(locale) = locale { - params.insert("locale".to_owned(), locale); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); + if let Some(ref locale) = locale { + params.insert("locale", locale); } - if let Some(market) = country { - params.insert("country".to_owned(), market.to_string()); + if let Some(ref market) = country { + params.insert("country", market.as_ref()); } let result = self.endpoint_get("browse/categories", ¶ms).await?; self.convert_result::(&result) @@ -1373,10 +1393,12 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - if let Some(market) = country { - params.insert("country".to_owned(), market.to_string()); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); + if let Some(ref market) = country { + params.insert("country", market.as_ref()); } let url = format!("browse/categories/{}/playlists", category_id); @@ -1411,7 +1433,8 @@ impl Spotify { payload: &Map, ) -> ClientResult { let mut params = Query::with_capacity(payload.len() + 1); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); + let limit = limit.into().unwrap_or(20).to_string(); + params.insert("limit", &limit); // TODO: this probably can be improved. let attributes = [ "acousticness", @@ -1429,6 +1452,7 @@ impl Spotify { "time_signature", "valence", ]; + let mut map_to_hold_owned_value = HashMap::new(); let prefixes = ["min", "max", "target"]; for attribute in attributes.iter() { for prefix in prefixes.iter() { @@ -1436,24 +1460,32 @@ impl Spotify { if let Some(value) = payload.get(¶m) { // TODO: not sure if this `to_string` is what we want. It // might add quotes to the strings. - params.insert(param, value.to_string()); + map_to_hold_owned_value.insert(param, value.to_string()); } } } - if let Some(seed_artists) = seed_artists { - params.insert("seed_artists".to_owned(), join_ids(seed_artists)); + for (ref key, ref value) in &map_to_hold_owned_value { + params.insert(key, value); } - if let Some(seed_genres) = seed_genres { - params.insert("seed_genres".to_owned(), seed_genres.join(",")); + let seed_artists = seed_artists.map(join_ids); + if let Some(ref seed_artists) = seed_artists { + params.insert("seed_artists", seed_artists); } - if let Some(seed_tracks) = seed_tracks { - params.insert("seed_tracks".to_owned(), join_ids(seed_tracks)); + let seed_genres = seed_genres.map(|x| x.join(",")); + if let Some(ref seed_genres) = seed_genres { + params.insert("seed_genres", seed_genres); } - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + + let seed_tracks = seed_tracks.map(join_ids); + if let Some(ref seed_tracks) = seed_tracks { + params.insert("seed_tracks", seed_tracks); + } + + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let result = self.endpoint_get("recommendations", ¶ms).await?; self.convert_result(&result) @@ -1535,18 +1567,14 @@ impl Spotify { additional_types: Option>, ) -> ClientResult> { let mut params = Query::new(); - if let Some(market) = market { - params.insert("country".to_owned(), market.to_string()); + if let Some(ref market) = market { + params.insert("country", market.as_ref()); } - if let Some(additional_types) = additional_types { - params.insert( - "additional_types".to_owned(), - additional_types - .iter() - .map(|x| x.to_string()) - .collect::>() - .join(","), - ); + let additional_types = + additional_types.map(|x| x.iter().map(|x| x.as_ref()).collect::>().join(",")); + + if let Some(ref additional_types) = additional_types { + params.insert("additional_types", additional_types); } let result = self.endpoint_get("me/player", ¶ms).await?; @@ -1573,18 +1601,13 @@ impl Spotify { additional_types: Option>, ) -> ClientResult> { let mut params = Query::new(); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } - if let Some(additional_types) = additional_types { - params.insert( - "additional_types".to_owned(), - additional_types - .iter() - .map(|x| x.to_string()) - .collect::>() - .join(","), - ); + let additional_types = + additional_types.map(|x| x.iter().map(|x| x.as_ref()).collect::>().join(",")); + if let Some(ref additional_types) = additional_types { + params.insert("additional_types", additional_types); } let result = self @@ -1781,7 +1804,7 @@ impl Spotify { #[maybe_async] pub async fn repeat(&self, state: RepeatState, device_id: Option) -> ClientResult<()> { let url = self.append_device_id( - &format!("me/player/repeat?state={}", state.to_string()), + &format!("me/player/repeat?state={}", state.as_ref()), device_id, ); self.endpoint_put(&url, &json!({})).await?; @@ -1881,8 +1904,10 @@ impl Spotify { offset: O, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); let result = self.endpoint_get("me/shows", ¶ms).await?; self.convert_result(&result) } @@ -1899,8 +1924,8 @@ impl Spotify { #[maybe_async] pub async fn get_a_show(&self, id: &ShowId, market: Option) -> ClientResult { let mut params = Query::new(); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let url = format!("shows/{}", id.id()); let result = self.endpoint_get(&url, ¶ms).await?; @@ -1922,9 +1947,10 @@ impl Spotify { market: Option, ) -> ClientResult> { let mut params = Query::with_capacity(1); - params.insert("ids".to_owned(), join_ids(ids)); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + let ids = join_ids(ids); + params.insert("ids", ids.as_ref()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let result = self.endpoint_get("shows", ¶ms).await?; self.convert_result::(&result) @@ -1952,10 +1978,12 @@ impl Spotify { market: Option, ) -> ClientResult> { let mut params = Query::with_capacity(2); - params.insert("limit".to_owned(), limit.into().unwrap_or(20).to_string()); - params.insert("offset".to_owned(), offset.into().unwrap_or(0).to_string()); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + let limit = limit.into().unwrap_or(20).to_string(); + let offset = offset.into().unwrap_or(0).to_string(); + params.insert("limit", &limit); + params.insert("offset", &offset); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let url = format!("shows/{}/episodes", id.id()); let result = self.endpoint_get(&url, ¶ms).await?; @@ -1979,8 +2007,8 @@ impl Spotify { ) -> ClientResult { let url = format!("episodes/{}", id.id()); let mut params = Query::new(); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let result = self.endpoint_get(&url, ¶ms).await?; @@ -2001,9 +2029,10 @@ impl Spotify { market: Option, ) -> ClientResult> { let mut params = Query::with_capacity(1); - params.insert("ids".to_owned(), join_ids(ids)); - if let Some(market) = market { - params.insert("market".to_owned(), market.to_string()); + let ids = join_ids(ids); + params.insert("ids", ids.as_ref()); + if let Some(ref market) = market { + params.insert("market", market.as_ref()); } let result = self.endpoint_get("episodes", ¶ms).await?; @@ -2023,7 +2052,8 @@ impl Spotify { ids: impl IntoIterator, ) -> ClientResult> { let mut params = Query::with_capacity(1); - params.insert("ids".to_owned(), join_ids(ids)); + let ids = join_ids(ids); + params.insert("ids", ids.as_str()); let result = self.endpoint_get("me/shows/contains", ¶ms).await?; self.convert_result(&result) } @@ -2045,7 +2075,7 @@ impl Spotify { let url = format!("me/shows?ids={}", join_ids(show_ids)); let mut params = json!({}); if let Some(market) = market { - json_insert!(params, "country", market.to_string()); + json_insert!(params, "country", market.as_ref()); } self.endpoint_delete(&url, ¶ms).await?; diff --git a/src/http/mod.rs b/src/http/mod.rs index e9c38653..edd5ea95 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -20,8 +20,8 @@ pub use self::reqwest::ReqwestClient as HTTPClient; pub use self::ureq::UreqClient as HTTPClient; pub type Headers = HashMap; -pub type Query = HashMap; -pub type Form = HashMap; +pub type Query<'a> = HashMap<&'a str, &'a str>; +pub type Form<'a> = HashMap<&'a str, &'a str>; pub mod headers { use crate::oauth2::Token; @@ -86,11 +86,11 @@ pub trait BaseHttpClient: Default + Clone + fmt::Debug { payload: &Value, ) -> ClientResult; - async fn post_form( + async fn post_form<'a>( &self, url: &str, headers: Option<&Headers>, - payload: &Form, + payload: &Form<'a>, ) -> ClientResult; async fn put( @@ -148,7 +148,7 @@ impl Spotify { &self, url: &str, headers: Option<&Headers>, - payload: &Query, + payload: &Query<'_>, ) -> ClientResult { let url = self.endpoint_url(url); self.http.get(&url, headers, payload).await @@ -172,7 +172,7 @@ impl Spotify { &self, url: &str, headers: Option<&Headers>, - payload: &Form, + payload: &Form<'_>, ) -> ClientResult { let url = self.endpoint_url(url); self.http.post_form(&url, headers, payload).await @@ -206,7 +206,11 @@ impl Spotify { /// autentication. #[inline] #[maybe_async] - pub(crate) async fn endpoint_get(&self, url: &str, payload: &Query) -> ClientResult { + pub(crate) async fn endpoint_get( + &self, + url: &str, + payload: &Query<'_>, + ) -> ClientResult { let headers = self.auth_headers()?; self.get(url, Some(&headers), payload).await } diff --git a/src/http/reqwest.rs b/src/http/reqwest.rs index f1282f38..cef391ae 100644 --- a/src/http/reqwest.rs +++ b/src/http/reqwest.rs @@ -118,11 +118,11 @@ impl BaseHttpClient for ReqwestClient { } #[inline] - async fn post_form( + async fn post_form<'a>( &self, url: &str, headers: Option<&Headers>, - payload: &Form, + payload: &Form<'a>, ) -> ClientResult { self.request(Method::POST, url, headers, |req| req.form(payload)) .await diff --git a/src/http/ureq.rs b/src/http/ureq.rs index 5206066c..e5da4b36 100644 --- a/src/http/ureq.rs +++ b/src/http/ureq.rs @@ -75,17 +75,17 @@ impl BaseHttpClient for UreqClient { } #[inline] - fn post_form( + fn post_form<'a>( &self, url: &str, headers: Option<&Headers>, - payload: &Form, + payload: &Form<'a>, ) -> ClientResult { let request = ureq::post(url); let sender = |req: Request| { let payload = payload .iter() - .map(|(key, val)| (key.as_str(), val.as_str())) + .map(|(key, val)| (*key, *val)) .collect::>(); req.send_form(&payload) diff --git a/src/model/enums/country.rs b/src/model/enums/country.rs index bd7ec845..55b3e0c4 100644 --- a/src/model/enums/country.rs +++ b/src/model/enums/country.rs @@ -1,11 +1,11 @@ use serde::{Deserialize, Serialize}; -use strum::ToString; +use strum::AsRefStr; /// ISO 3166-1 alpha-2 country code, from /// [country-list](https://datahub.io/core/country-list) /// /// [Reference](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] pub enum Country { #[strum(serialize = "AF")] #[serde(rename = "AF")] diff --git a/src/model/enums/misc.rs b/src/model/enums/misc.rs index 3dbe5b4f..e7ee0dce 100644 --- a/src/model/enums/misc.rs +++ b/src/model/enums/misc.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use strum::ToString; +use strum::AsRefStr; use super::Country; @@ -8,7 +8,7 @@ use super::Country; /// `toggling_shuffle`, `toggling_repeat_track`, `transferring_playback`. /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/object-model/#disallows-object) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, Hash, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, Hash, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum DisallowKey { @@ -27,7 +27,7 @@ pub enum DisallowKey { /// Time range: `long-term`, `medium-term`, `short-term`. /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/personalization/get-users-top-artists-and-tracks/) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum TimeRange { @@ -39,7 +39,7 @@ pub enum TimeRange { /// Repeat state: `track`, `context` or `off`. /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/player/set-repeat-mode-on-users-playback/) -#[derive(Clone, Debug, Copy, Serialize, Deserialize, PartialEq, Eq, ToString)] +#[derive(Clone, Debug, Copy, Serialize, Deserialize, PartialEq, Eq, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum RepeatState { @@ -51,7 +51,7 @@ pub enum RepeatState { /// Type for include_external: `audio`. /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/search/search/) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum IncludeExternal { @@ -61,7 +61,7 @@ pub enum IncludeExternal { /// Date precision: `year`, `month`, `day`. /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/object-model/): -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum DatePrecision { @@ -73,7 +73,7 @@ pub enum DatePrecision { /// The reason for the restriction: `market`, `product`, `explicit` /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/object-model/#track-restriction-object) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum RestrictionReason { @@ -87,7 +87,7 @@ pub enum RestrictionReason { /// a -1 for `no result` /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/tracks/get-audio-analysis/#section-object) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] pub enum Modality { Minor = 0, Major = 1, @@ -102,12 +102,15 @@ pub enum Market { Country(Country), FromToken, } +pub trait AsRefStr { + fn as_ref(&self) -> &str; +} -impl ToString for Market { - fn to_string(&self) -> String { +impl AsRefStr for Market { + fn as_ref(&self) -> &str { match self { - Market::Country(c) => c.to_string(), - Market::FromToken => "from_token".to_string(), + Market::Country(country) => country.as_ref(), + Market::FromToken => "from_token", } } } diff --git a/src/model/enums/types.rs b/src/model/enums/types.rs index 33b7d7e3..2115e408 100644 --- a/src/model/enums/types.rs +++ b/src/model/enums/types.rs @@ -1,11 +1,11 @@ use serde::{Deserialize, Serialize}; -use strum::{Display, EnumString, ToString}; +use strum::{AsRefStr, Display, EnumString}; /// Copyright type: `C` = the copyright, `P` = the sound recording (performance) /// copyright. /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/object-model/#copyright-object) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] pub enum CopyrightType { #[strum(serialize = "P")] #[serde(rename = "P")] @@ -18,7 +18,7 @@ pub enum CopyrightType { /// Album type: `album`, `single`, `appears_on`, `compilation` /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/object-model/#album-object-full) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum AlbumType { @@ -29,7 +29,9 @@ pub enum AlbumType { } /// Type: `artist`, `album`, `track`, `playlist`, `show` or `episode` -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, Display, EnumString)] +#[derive( + Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, Display, EnumString, AsRefStr, +)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum Type { @@ -45,7 +47,7 @@ pub enum Type { /// Additional typs: `track`, `episode` /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/player/get-information-about-the-users-current-playback/) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum AdditionalType { @@ -56,7 +58,7 @@ pub enum AdditionalType { /// Currently playing type: `track`, `episode`, `ad`, `unknown` /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/player/get-the-users-currently-playing-track/) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum CurrentlyPlayingType { @@ -71,7 +73,7 @@ pub enum CurrentlyPlayingType { /// Type for search: `artist`, `album`, `track`, `playlist`, `show`, `episode` /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/#category-search) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum SearchType { @@ -88,7 +90,7 @@ pub enum SearchType { /// (The subscription level "open" can be considered the same as "free".) /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/users-profile/get-current-users-profile/) -#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, ToString)] +#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Debug, AsRefStr)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum SubscriptionLevel { @@ -100,7 +102,7 @@ pub enum SubscriptionLevel { /// Device Type: `computer`, `smartphone`, `speaker`, `TV` /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/player/get-a-users-available-devices/#device-types) -#[derive(Clone, Debug, Serialize, Deserialize, ToString, PartialEq, Eq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, AsRefStr)] #[strum(serialize_all = "snake_case")] pub enum DeviceType { Computer, @@ -121,7 +123,7 @@ pub enum DeviceType { /// Recommendations seed type /// /// [Reference](https://developer.spotify.com/documentation/web-api/reference/object-model/#recommendations-seed-object) -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, AsRefStr)] #[serde(rename_all = "snake_case")] pub enum RecommendationsSeedType { Artist, diff --git a/src/oauth2.rs b/src/oauth2.rs index 603f5478..b37fe14b 100644 --- a/src/oauth2.rs +++ b/src/oauth2.rs @@ -246,7 +246,7 @@ impl Spotify { /// Sends a request to Spotify for an access token. #[maybe_async] - async fn fetch_access_token(&self, payload: &Form) -> ClientResult { + async fn fetch_access_token(&self, payload: &Form<'_>) -> ClientResult { // This request uses a specific content type, and the client ID/secret // as the authentication, since the access token isn't available yet. let mut head = Headers::new(); @@ -272,11 +272,8 @@ impl Spotify { refresh_token: &str, ) -> ClientResult<()> { let mut data = Form::new(); - data.insert(headers::REFRESH_TOKEN.to_owned(), refresh_token.to_owned()); - data.insert( - headers::GRANT_TYPE.to_owned(), - headers::GRANT_REFRESH_TOKEN.to_owned(), - ); + data.insert(headers::REFRESH_TOKEN, refresh_token); + data.insert(headers::GRANT_TYPE, headers::GRANT_REFRESH_TOKEN); let mut tok = self.fetch_access_token(&data).await?; tok.refresh_token = Some(refresh_token.to_string()); @@ -299,10 +296,7 @@ impl Spotify { #[maybe_async] pub async fn request_client_token_without_cache(&mut self) -> ClientResult<()> { let mut data = Form::new(); - data.insert( - headers::GRANT_TYPE.to_owned(), - headers::GRANT_CLIENT_CREDS.to_owned(), - ); + data.insert(headers::GRANT_TYPE, headers::GRANT_CLIENT_CREDS); self.token = Some(self.fetch_access_token(&data).await?); @@ -338,22 +332,17 @@ impl Spotify { pub async fn request_user_token_without_cache(&mut self, code: &str) -> ClientResult<()> { let oauth = self.get_oauth()?; let mut data = Form::new(); - data.insert( - headers::GRANT_TYPE.to_owned(), - headers::GRANT_AUTH_CODE.to_owned(), - ); - data.insert(headers::REDIRECT_URI.to_owned(), oauth.redirect_uri.clone()); - data.insert(headers::CODE.to_owned(), code.to_owned()); - data.insert( - headers::SCOPE.to_owned(), - oauth - .scope - .clone() - .into_iter() - .collect::>() - .join(" "), - ); - data.insert(headers::STATE.to_owned(), oauth.state.clone()); + let scopes = oauth + .scope + .clone() + .into_iter() + .collect::>() + .join(" "); + data.insert(headers::GRANT_TYPE, headers::GRANT_AUTH_CODE); + data.insert(headers::REDIRECT_URI, oauth.redirect_uri.as_ref()); + data.insert(headers::CODE, code); + data.insert(headers::SCOPE, scopes.as_ref()); + data.insert(headers::STATE, oauth.state.as_ref()); self.token = Some(self.fetch_access_token(&data).await?); diff --git a/tests/test_enums.rs b/tests/test_enums.rs index c234d617..e80f65be 100644 --- a/tests/test_enums.rs +++ b/tests/test_enums.rs @@ -3,71 +3,71 @@ use rspotify::model::*; #[test] fn test_include_external() { let audio = IncludeExternal::Audio; - assert_eq!("audio".to_string(), audio.to_string()); + assert_eq!("audio", audio.as_ref()); } #[test] fn test_repeat_state() { let context = RepeatState::Context; - assert_eq!(context.to_string(), "context".to_string()); + assert_eq!(context.as_ref(), "context"); } #[test] fn test_disallow_key() { let toggling_shuffle = DisallowKey::TogglingShuffle; - assert_eq!(toggling_shuffle.to_string(), "toggling_shuffle".to_string()); + assert_eq!(toggling_shuffle.as_ref(), "toggling_shuffle"); } #[test] fn test_time_range() { let medium_range = TimeRange::MediumTerm; - assert_eq!(medium_range.to_string(), "medium_term".to_string()); + assert_eq!(medium_range.as_ref(), "medium_term"); } #[test] fn test_date_precision() { let month = DatePrecision::Month; - assert_eq!(month.to_string(), "month".to_string()); + assert_eq!(month.as_ref(), "month"); } #[test] fn test_album_type_convert_from_str() { let appears_on = AlbumType::AppearsOn; - assert_eq!("appears_on".to_string(), appears_on.to_string()); + assert_eq!("appears_on", appears_on.as_ref()); } #[test] fn test_convert_search_type_from_str() { let search_type = SearchType::Artist; - assert_eq!("artist".to_string(), search_type.to_string()); + assert_eq!("artist", search_type.as_ref()); } #[test] fn test_type_convert_from_str() { let artist = Type::Artist; - assert_eq!(artist.to_string(), "artist".to_string()); + assert_eq!(artist.as_ref(), "artist"); } #[test] fn test_additional_type() { let episode = AdditionalType::Episode; - assert_eq!(episode.to_string(), "episode".to_string()); + assert_eq!(episode.as_ref(), "episode"); } #[test] fn test_current_playing_type() { let ad = CurrentlyPlayingType::Advertisement; - assert_eq!(ad.to_string(), "ad".to_string()); + assert_eq!(ad.as_ref(), "ad"); } #[test] fn test_search_type() { let episode = SearchType::Episode; - assert_eq!(episode.to_string(), "episode".to_string()); + assert_eq!(episode.as_ref(), "episode"); } #[test] fn test_convert_country_from_str() { let zimbabwe = Country::Zimbabwe; - assert_eq!(zimbabwe.to_string(), "ZW".to_string()); + assert_eq!(zimbabwe.as_ref(), "ZW"); }