diff options
author | alyx <alyx@aleteoryx.me> | 2023-08-09 00:44:10 -0400 |
---|---|---|
committer | alyx <alyx@aleteoryx.me> | 2023-08-09 00:44:10 -0400 |
commit | d796f6762acb52cf2ab202d76382915064f0d534 (patch) | |
tree | cf22c65e025345f0f15e77153f21c312a6a827f8 | |
download | lfm_embed-d796f6762acb52cf2ab202d76382915064f0d534.tar.gz lfm_embed-d796f6762acb52cf2ab202d76382915064f0d534.tar.bz2 lfm_embed-d796f6762acb52cf2ab202d76382915064f0d534.zip |
API deserialization structs
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | src/deserialize.rs | 173 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/main.rs | 3 |
5 files changed, 189 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e1193dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +*~ +.#* +\#* diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ab70ee6 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "lfm_embed" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/deserialize.rs b/src/deserialize.rs new file mode 100644 index 0000000..4cedc9f --- /dev/null +++ b/src/deserialize.rs @@ -0,0 +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 +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5d0a682 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +mod deserialize; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} |