@@ 1,173 @@
+use serde::{Deserialize, Deserializer, de};
+use serde_json::Value;
+
+use std::collections::HashMap;
+use std::sync::Arc;
+
+fn str_num<'de, D, T>(d: D) -> Result<T, D::Error> where D: Deserializer<'de>, T: From<u64> {
+ struct Visitor;
+ impl<'v> de::Visitor<'v> for Visitor {
+ type Value = u64;
+ fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "a value which can be interpreted as a uint")
+ }
+ fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+ where
+ E: de::Error
+ {
+ v.parse().map_err(|_| de::Error::invalid_value(de::Unexpected::Str(v), &"a string which can be parsed as a uint"))
+ }
+ fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
+ where
+ E: de::Error
+ {
+ Ok(v)
+ }
+ }
+ d.deserialize_any(Visitor).map(Into::into)
+}
+fn str_bool<'de, D, T>(d: D) -> Result<T, D::Error> where D: Deserializer<'de>, T: From<bool>{
+ struct Visitor;
+ impl<'v> de::Visitor<'v> for Visitor {
+ type Value = bool;
+ fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "a value which can be interpreted as a uint")
+ }
+ fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+ where
+ E: de::Error
+ {
+ match v.to_ascii_lowercase().as_str() {
+ "true" | "1" => Ok(true),
+ "false" | "0" => Ok(false),
+ _ => Err(de::Error::invalid_value(de::Unexpected::Str(v), &"a string which can be parsed as a bool"))
+ }
+ }
+ fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
+ where
+ E: de::Error
+ {
+ Ok(v)
+ }
+ }
+ d.deserialize_any(Visitor).map(Into::into)
+}
+
+
+#[derive(Deserialize, Debug)]
+pub struct TimeStamp {
+ #[serde(alias = "unixtime")]
+ #[serde(alias = "uts")]
+ #[serde(deserialize_with = "str_num")]
+ pub unix_timestamp: u64,
+ #[serde(rename = "#text")]
+ pub text: Value
+}
+
+#[derive(Deserialize, Debug)]
+pub struct Artist {
+ #[serde(rename = "mbid")]
+ pub uuid: Arc<str>,
+ #[serde(alias = "#text")]
+ pub name: Arc<str>,
+
+ #[serde(default)]
+ #[serde(rename = "image")]
+ pub images: Vec<Image>,
+ pub #[serde(default)]
+ url: Option<Arc<str>>
+}
+
+#[derive(Deserialize, Debug)]
+#[serde(rename_all = "lowercase")]
+pub enum ImageSize {
+ Small,
+ Medium,
+ Large,
+ ExtraLarge
+}
+
+#[derive(Deserialize, Debug)]
+pub struct Image {
+ pub size: ImageSize,
+ #[serde(rename = "#text")]
+ pub url: Arc<str>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct Album {
+ #[serde(rename = "mbid")]
+ pub uuid: Arc<str>,
+ #[serde(rename = "#text")]
+ pub name: Arc<str>,
+}
+
+#[derive(Default, Deserialize, Debug)]
+pub struct TrackAttr {
+ #[serde(default)]
+ #[serde(deserialize_with = "str_bool")]
+ pub nowplaying: bool,
+ #[serde(flatten)]
+ pub rest: HashMap<Arc<str>, Value>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct Track {
+ pub artist: Artist,
+ #[serde(deserialize_with = "str_bool")]
+ pub streamable: bool,
+ #[serde(rename = "image")]
+ pub images: Vec<Image>,
+ #[serde(rename = "mbid")]
+ pub uuid: Arc<str>,
+ pub album: Album,
+ pub name: Arc<str>,
+ #[serde(rename = "@attr")]
+ #[serde(default)]
+ pub attr: TrackAttr,
+ pub url: Arc<str>,
+
+ #[serde(default)]
+ #[serde(deserialize_with = "str_bool")]
+ pub loved: Option<bool>,
+ #[serde(default)]
+ pub date: Option<TimeStamp>
+}
+
+#[derive(Deserialize, Debug)]
+pub struct RecentTracks {
+ pub track: Vec<Track>
+}
+#[derive(Deserialize, Debug)]
+pub struct GetRecentTracks {
+ pub recenttracks: RecentTracks
+}
+
+#[derive(Deserialize, Debug)]
+pub struct User {
+ pub name: Arc<str>,
+ #[serde(deserialize_with = "str_bool")]
+ pub subscriber: bool,
+ pub realname: Arc<str>,
+ #[serde(deserialize_with = "str_num")]
+ pub playcount: u64,
+ #[serde(deserialize_with = "str_num")]
+ pub artist_count: u64,
+ #[serde(deserialize_with = "str_num")]
+ pub playlists: u64,
+ #[serde(deserialize_with = "str_num")]
+ pub track_count: u64,
+ #[serde(deserialize_with = "str_num")]
+ pub album_count: u64,
+
+ #[serde(rename = "image")]
+ pub images: Vec<Image>,
+
+ pub registered: TimeStamp,
+ pub url: Arc<str>
+}
+
+#[derive(Deserialize, Debug)]
+pub struct GetUserInfo {
+ pub user: User
+}