mparsed/src/lib.rs

146 lines
4.9 KiB
Rust

use serde::de;
use std::collections::HashMap;
mod error;
use error::{Error, MpdResult};
mod structs;
pub use structs::{Position, Track};
/// some unprintable character to separate repeated keys
const SEPARATOR: char = '\x02';
pub fn deserialize_response<'a, I: Iterator<Item = &'a str>, T: de::DeserializeOwned>(input: I) -> MpdResult<T> {
let mut map: HashMap<String, String> = HashMap::new();
for line in input {
if line.starts_with("OK") {
break;
} else if let Some(message) = line.strip_prefix("ACK") {
return Err(Error::from_str(message.trim()));
}
let mut fields = line.splitn(2, ": ");
match (fields.next(), fields.next()) {
(Some(k), Some(v)) => {
if let Some(existing) = map.get_mut(k) {
existing.push(SEPARATOR);
existing.push_str(v);
} else {
map.insert(k.to_string(), v.to_string());
}
}
_ => panic!("invalid response line: {:?}", line),
}
}
// Eventually, I’d like to use my own deserializer instead of envy
Ok(envy::from_iter(map).unwrap())
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::DateTime;
#[test]
fn track_de_test() {
let input_str = "file: American Pie.flac
Last-Modified: 2019-12-16T21:38:54Z
Album: American Pie
Artist: Don McLean
Date: 1979
Genre: Rock
Title: American Pie
Track: 1
Time: 512
duration: 512.380
Pos: 1367
Id: 1368
OK";
let t: Track = deserialize_response(input_str.lines()).unwrap();
assert_eq!(
t,
Track {
file: "American Pie.flac".to_string(),
last_modified: Some(DateTime::parse_from_rfc3339("2019-12-16T21:38:54Z").unwrap()),
album: Some("American Pie".to_string()),
artist: Some("Don McLean".to_string()),
date: Some(1979),
genre: Some("Rock".to_string()),
title: Some("American Pie".to_string()),
track: Some(Position {
item_position: 1,
total_items: None,
}),
duration: std::time::Duration::from_secs_f64(512.380),
pos: 1367,
id: 1368,
..Track::default()
}
);
}
#[test]
fn repeated_field_test() {
let input_str = r#"file: 06 Symphonie No. 41 en ut majeur, K. 551 _Jupiter_ I. Allegro Vivace.flac
Last-Modified: 2018-11-11T09:01:54Z
Album: Symphonies n°40 & n°41
AlbumArtist: Wolfgang Amadeus Mozart; Royal Philharmonic Orchestra, Jane Glover
AlbumArtistSort: Mozart, Wolfgang Amadeus; Royal Philharmonic Orchestra, Glover, Jane
Artist: Wolfgang Amadeus Mozart
ArtistSort: Mozart, Wolfgang Amadeus
Composer: Wolfgang Amadeus Mozart
Date: 2005
Disc: 1
Disc: 1
MUSICBRAINZ_ALBUMARTISTID: b972f589-fb0e-474e-b64a-803b0364fa75
MUSICBRAINZ_ALBUMID: 688d9252-f897-4ab6-879d-5cb83bb71087
MUSICBRAINZ_ARTISTID: b972f589-fb0e-474e-b64a-803b0364fa75
MUSICBRAINZ_RELEASETRACKID: 54a2632f-fa98-3713-bd75-d7effc03d0b1
MUSICBRAINZ_TRACKID: 2dd10dd8-e8de-4479-a092-9a04c2760fd6
OriginalDate: 1993
Title: Symphonie No. 41 en ut majeur, K. 551 "Jupiter": I. Allegro Vivace
Track: 6
Track: 6
Time: 683
Performer: Royal Philharmonic Orchestra
duration: 682.840
Performer: Jane Glover
Pos: 3439
Id: 3440
OK"#;
let t: Track = deserialize_response(input_str.lines()).unwrap();
assert_eq!(
t,
Track {
file: "06 Symphonie No. 41 en ut majeur, K. 551 _Jupiter_ I. Allegro Vivace.flac".to_string(),
last_modified: Some(DateTime::parse_from_rfc3339("2018-11-11T09:01:54Z").unwrap()),
album: Some("Symphonies n°40 & n°41".to_string()),
artist: Some("Wolfgang Amadeus Mozart".to_string()),
artist_sort: Some("Mozart, Wolfgang Amadeus".to_string()),
album_artist: Some("Wolfgang Amadeus Mozart; Royal Philharmonic Orchestra, Jane Glover".to_string()),
album_artist_sort: Some("Mozart, Wolfgang Amadeus; Royal Philharmonic Orchestra, Glover, Jane".to_string()),
composer: Some("Wolfgang Amadeus Mozart".to_string()),
date: Some(2005),
original_date: Some(1993),
title: Some("Symphonie No. 41 en ut majeur, K. 551 \"Jupiter\": I. Allegro Vivace".to_string()),
disc: Some(Position {
item_position: 1,
total_items: Some(1),
}),
track: Some(Position {
item_position: 6,
total_items: Some(6),
}),
duration: std::time::Duration::from_secs_f64(682.840),
pos: 3439,
id: 3440,
performers: vec!["Royal Philharmonic Orchestra".to_string(), "Jane Glover".to_string()],
musicbrainz_albumartistid: Some("b972f589-fb0e-474e-b64a-803b0364fa75".to_string()),
musicbrainz_albumid: Some("688d9252-f897-4ab6-879d-5cb83bb71087".to_string()),
musicbrainz_artistid: Some("b972f589-fb0e-474e-b64a-803b0364fa75".to_string()),
musicbrainz_releasetrackid: Some("54a2632f-fa98-3713-bd75-d7effc03d0b1".to_string()),
musicbrainz_trackid: Some("2dd10dd8-e8de-4479-a092-9a04c2760fd6".to_string()),
..Track::default()
}
);
}
}