Add playlist info
This is also the first occurence of multiple structs in one response. The Itertools.batching approach seems to work quite well.
This commit is contained in:
parent
fe2730a7d6
commit
c374a04417
94
src/lib.rs
94
src/lib.rs
@ -2,6 +2,7 @@ use serde::de;
|
||||
use std::collections::HashMap;
|
||||
mod error;
|
||||
use error::{Error, MpdResult};
|
||||
use itertools::Itertools;
|
||||
mod structs;
|
||||
pub use structs::{Position, Status, Track};
|
||||
|
||||
@ -34,6 +35,34 @@ pub fn deserialize_response<'a, I: Iterator<Item = &'a str>, T: de::DeserializeO
|
||||
Ok(envy::from_iter(map).unwrap())
|
||||
}
|
||||
|
||||
pub fn read_playlist_info<'a, I: Iterator<Item = &'a str>>(input: I) -> MpdResult<Vec<Track>> {
|
||||
input
|
||||
.peekable()
|
||||
.batching(|it| {
|
||||
let mut v = match it.next() {
|
||||
// if the playlist is empty or we’ve reached the end,
|
||||
// the response is only the `OK` line.
|
||||
Some("OK") => return None,
|
||||
// otherwise this is the file attribute and thus the first key-value of this track
|
||||
Some(s) => vec![s],
|
||||
_ => return None,
|
||||
};
|
||||
// Only peek here in case we encounter the `file:` line which we still need for the next track.
|
||||
while let Some(l) = it.peek() {
|
||||
if l.starts_with("file:") {
|
||||
return Some(v);
|
||||
}
|
||||
if l.starts_with("OK") {
|
||||
return Some(v);
|
||||
}
|
||||
v.push(it.next().unwrap());
|
||||
}
|
||||
None
|
||||
})
|
||||
.map(|b| deserialize_response(b.into_iter()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -186,4 +215,69 @@ OK";
|
||||
}
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn de_playlist_test() {
|
||||
let input_str = "file: 137 A New World.mp3
|
||||
Last-Modified: 2018-03-07T13:11:43Z
|
||||
Artist: Arata Iiyoshi
|
||||
Title: A New World
|
||||
Album: Pokemon Mystery Dungeon: Explorers of Sky
|
||||
duration: 225.802
|
||||
Pos: 1000
|
||||
Id: 6365
|
||||
file: 139 Thoughts For Friends.mp3
|
||||
Last-Modified: 2018-03-07T13:11:43Z
|
||||
Artist: Arata Iiyoshi
|
||||
Title: Thoughts For Friends
|
||||
Album: Pokemon Mystery Dungeon: Explorers of Sky
|
||||
duration: 66.560
|
||||
Pos: 1001
|
||||
Id: 6366
|
||||
file: 140 A Message On the Wind.mp3
|
||||
Last-Modified: 2018-03-07T13:11:43Z
|
||||
Artist: Arata Iiyoshi
|
||||
Title: A Message On the Wind
|
||||
Album: Pokemon Mystery Dungeon: Explorers of Sky
|
||||
duration: 50.155
|
||||
Pos: 1002
|
||||
Id: 6367
|
||||
OK";
|
||||
let queue = read_playlist_info(input_str.lines());
|
||||
let first_track = Track {
|
||||
file: "137 A New World.mp3".into(),
|
||||
title: Some("A New World".into()),
|
||||
artist: Some("Arata Iiyoshi".into()),
|
||||
album: Some("Pokemon Mystery Dungeon: Explorers of Sky".into()),
|
||||
last_modified: Some(DateTime::parse_from_rfc3339("2018-03-07T13:11:43Z").unwrap()),
|
||||
duration: Some(Duration::from_secs_f64(225.802)),
|
||||
pos: 1000,
|
||||
id: 6365,
|
||||
..Track::default()
|
||||
};
|
||||
assert_eq!(
|
||||
queue,
|
||||
Ok(vec![
|
||||
first_track.clone(),
|
||||
Track {
|
||||
file: "139 Thoughts For Friends.mp3".into(),
|
||||
title: Some("Thoughts For Friends".into()),
|
||||
duration: Some(Duration::from_secs_f64(66.56)),
|
||||
pos: 1001,
|
||||
id: 6366,
|
||||
..first_track.clone()
|
||||
},
|
||||
Track {
|
||||
file: "140 A Message On the Wind.mp3".into(),
|
||||
title: Some("A Message On the Wind".into()),
|
||||
duration: Some(Duration::from_secs_f64(50.155)),
|
||||
pos: 1002,
|
||||
id: 6367,
|
||||
..first_track
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
let queue = read_playlist_info("OK".lines());
|
||||
assert_eq!(queue, Ok(vec![]));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user