aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Cargo.toml8
-rw-r--r--src/deserialize.rs173
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs3
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!");
+}