Generify reponse chunking

This commit is contained in:
kageru 2020-06-21 23:37:19 +02:00
parent e12ae75e73
commit 1e39119e09
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2

View File

@ -9,7 +9,7 @@ pub use structs::{Position, State, Stats, Status, Track, UnitResponse};
/// 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> {
pub fn parse_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") {
@ -34,7 +34,7 @@ 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>> {
pub fn parse_response_vec<'a, 'b, I: Iterator<Item = &'a str>, T: de::DeserializeOwned>(input: I, first_key: &'b str) -> MpdResult<Vec<T>> {
input
.peekable()
.batching(|it| {
@ -48,7 +48,7 @@ pub fn read_playlist_info<'a, I: Iterator<Item = &'a str>>(input: I) -> MpdResul
};
// 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:") {
if l.starts_with(first_key) {
return Some(v);
}
if l.starts_with("OK") {
@ -58,7 +58,7 @@ pub fn read_playlist_info<'a, I: Iterator<Item = &'a str>>(input: I) -> MpdResul
}
None
})
.map(|b| deserialize_response(b.into_iter()))
.map(|b| parse_response(b.into_iter()))
.collect()
}
@ -83,7 +83,7 @@ duration: 512.380
Pos: 1367
Id: 1368
OK";
let t: Track = deserialize_response(input_str.lines()).unwrap();
let t: Track = parse_response(input_str.lines()).unwrap();
assert_eq!(
t,
Track {
@ -135,7 +135,7 @@ Performer: Jane Glover
Pos: 3439
Id: 3440
OK"#;
let t: Track = deserialize_response(input_str.lines()).unwrap();
let t: Track = parse_response(input_str.lines()).unwrap();
assert_eq!(
t,
Track {
@ -192,7 +192,7 @@ audio: 44100:16:2
nextsong: 4036
nextsongid: 4037
OK";
let s: Status = deserialize_response(input_str.lines()).unwrap();
let s: Status = parse_response(input_str.lines()).unwrap();
assert_eq!(
s,
Status {
@ -241,7 +241,7 @@ duration: 50.155
Pos: 1002
Id: 6367
OK";
let queue = read_playlist_info(input_str.lines());
let queue = parse_response_vec(input_str.lines(), "file:");
let first_track = Track {
file: "137 A New World.mp3".into(),
title: Some("A New World".into()),
@ -276,8 +276,8 @@ OK";
])
);
let queue = read_playlist_info("OK".lines());
assert_eq!(queue, Ok(vec![]));
let queue = parse_response_vec("OK".lines(), "file:");
assert_eq!(queue, Ok(Vec::<Track>::new()));
}
#[test]
@ -290,7 +290,7 @@ songs: 40322
db_playtime: 11620284
db_update: 1588433046
OK";
let s: Stats = deserialize_response(input_str.lines()).unwrap();
let s: Stats = parse_response(input_str.lines()).unwrap();
assert_eq!(
s,
Stats {
@ -308,11 +308,11 @@ OK";
#[test]
fn de_unit_response_test() {
let success = "OK";
let r: Result<UnitResponse, _> = deserialize_response(success.lines());
let r: Result<UnitResponse, _> = parse_response(success.lines());
assert_eq!(r, Ok(UnitResponse {}));
let failure = r#"ACK [2@0] {consume} wrong number of arguments for "consume""#;
let r: Result<UnitResponse, _> = deserialize_response(failure.lines());
let r: Result<UnitResponse, _> = parse_response(failure.lines());
assert_eq!(
r,
Err(error::Error::from_str(r#"[2@0] {consume} wrong number of arguments for "consume""#))