92 lines
2.9 KiB
Rust
92 lines
2.9 KiB
Rust
use helpers::*;
|
|
use serde::Deserialize;
|
|
use std::time::Duration;
|
|
|
|
#[derive(Deserialize, Clone, Debug, Default, PartialEq)]
|
|
pub struct Track {
|
|
pub file: String,
|
|
pub artist_sort: Option<String>,
|
|
pub album_artist: Option<String>,
|
|
pub album_sort: Option<String>,
|
|
pub album_artist_sort: Option<String>,
|
|
#[serde(deserialize_with = "string_or_vec")]
|
|
#[serde(default)]
|
|
#[serde(rename = "performer")]
|
|
pub performers: Vec<String>,
|
|
pub genre: Option<String>,
|
|
pub title: Option<String>,
|
|
pub track: Option<u32>,
|
|
pub album: Option<String>,
|
|
pub artist: Option<String>,
|
|
pub pos: u32,
|
|
pub id: u32,
|
|
// TODO: use proper time here
|
|
#[serde(rename = "last-modified")]
|
|
pub last_modified: Option<String>,
|
|
pub original_date: Option<u16>,
|
|
// probably not needed. it’s just the duration but as an int
|
|
// pub time: u16,
|
|
pub format: Option<String>,
|
|
#[serde(deserialize_with = "de_time_float")]
|
|
pub duration: Duration,
|
|
pub label: Option<String>,
|
|
pub date: Option<u16>,
|
|
pub disc: Option<u16>,
|
|
pub musicbraiz_trackid: Option<String>,
|
|
pub musicbrainz_albumid: Option<String>,
|
|
pub musicbrainz_albumartistid: Option<String>,
|
|
pub musicbrainz_artistid: Option<String>,
|
|
pub musicbraiz_releasetrackid: Option<String>,
|
|
pub composer: Option<String>,
|
|
}
|
|
|
|
/// 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<Duration, D::Error>
|
|
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<Duration, D::Error>
|
|
where
|
|
D: de::Deserializer<'de>,
|
|
{
|
|
f64::deserialize(deserializer).map(Duration::from_secs_f64)
|
|
}
|
|
|
|
pub fn string_or_vec<'de, D>(deserializer: D) -> Result<Vec<String>, 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<bool, D::Error>
|
|
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",
|
|
)),
|
|
}
|
|
}
|
|
}
|