use helpers::*; use serde::Deserialize; use std::time::Duration; #[derive(Deserialize, Clone, Debug)] pub struct Track { pub file: String, pub artist_sort: Option, pub album_artist: Option, pub album_sort: Option, pub album_artist_sort: Option, #[serde(deserialize_with = "string_or_vec")] #[serde(default)] #[serde(rename = "performer")] pub performers: Vec, pub genre: Option, pub title: Option, pub track: Option, pub album: Option, pub artist: Option, pub pos: Option, pub id: Option, // TODO: use proper time here pub last_modified: Option, pub original_date: Option, pub time: Option, pub format: Option, #[serde(deserialize_with = "de_time_float")] pub duration: Duration, pub label: Option, pub date: Option, pub disc: Option, pub musicbraiz_trackid: Option, pub musicbrainz_albumid: Option, pub musicbrainz_albumartistid: Option, pub musicbrainz_artistid: Option, pub musicbraiz_releasetrackid: Option, pub composer: Option, } /// Deserialization helpers to handle the quirks of mpd’s output. mod helpers { use crate::SEPARATOR; use serde::de; use serde::Deserialize; use std::time::Duration; /// Deserialize time from an integer that represents the seconds. /// mpd uses int for the database stats (e.g. total time played). pub fn de_time_int<'de, D>(deserializer: D) -> Result where D: de::Deserializer<'de>, { u64::deserialize(deserializer).map(Duration::from_secs) } /// Deserialize time from a float that represents the seconds. /// mpd uses floats for the current status (e.g. time elapsed in song). pub fn de_time_float<'de, D>(deserializer: D) -> Result where D: de::Deserializer<'de>, { f64::deserialize(deserializer).map(Duration::from_secs_f64) } pub fn string_or_vec<'de, D>(deserializer: D) -> Result, D::Error> where D: de::Deserializer<'de>, { String::deserialize(deserializer) .map(|s| s.split(SEPARATOR).map(std::string::String::from).collect()) } /// mpd uses bints (0 or 1) to represent booleans, /// so we need a special parser for those. pub fn de_bint<'de, D>(deserializer: D) -> Result where D: de::Deserializer<'de>, { match u8::deserialize(deserializer)? { 0 => Ok(false), 1 => Ok(true), n => Err(de::Error::invalid_value( de::Unexpected::Unsigned(n as u64), &"zero or one", )), } } }