mparsed/src/structs.rs

90 lines
2.8 KiB
Rust

use helpers::*;
use serde::Deserialize;
use std::time::Duration;
#[derive(Deserialize, Clone, Debug)]
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: Option<u32>,
pub id: Option<u32>,
// TODO: use proper time here
pub last_modified: Option<String>,
pub original_date: Option<String>,
pub time: Option<String>,
pub format: Option<String>,
#[serde(deserialize_with = "de_time_float")]
pub duration: Duration,
pub label: Option<String>,
pub date: Option<String>,
pub disc: Option<u32>,
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",
)),
}
}
}