diff --git a/src/commands/music_database/list.rs b/src/commands/music_database/list.rs index e843dbb..6b133c2 100644 --- a/src/commands/music_database/list.rs +++ b/src/commands/music_database/list.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use crate::{ commands::{Command, Request, RequestParserError, RequestParserResult, ResponseParserError}, - common::{GroupType, TagName}, + common::{GroupType, TagName, WindowRange}, filter::Filter, request_tokenizer::RequestTokenizer, response_tokenizer::{ResponseAttributes, expect_property_type}, @@ -13,8 +13,9 @@ pub struct List; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ListRequest { tagname: TagName, - filter: Filter, - group: Option, + filter: Option, + groups: Vec, + window: Option, } pub type ListResponse = Vec; @@ -25,10 +26,16 @@ impl Command for List { const COMMAND: &'static str = "list"; fn serialize_request(&self, request: Self::Request) -> String { - let mut cmd = format!("{} {} {}", Self::COMMAND, request.tagname, request.filter); - if let Some(group) = request.group { + let mut cmd = match &request.filter { + Some(f) => format!("{} {} {}", Self::COMMAND, request.tagname, f), + None => format!("{} {}", Self::COMMAND, request.tagname), + }; + for group in request.groups { cmd.push_str(&format!(" group {}", group)); } + if let Some(window) = request.window { + cmd.push_str(&format!(" window {}", window)); + } cmd } @@ -38,28 +45,46 @@ impl Command for List { .parse() .map_err(|_| RequestParserError::SyntaxError(1, tagname.to_owned()))?; - // TODO: This should be optional - let filter = match parts.next() { - Some(f) => { - Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))? - } - None => return Err(RequestParserError::UnexpectedEOF), - }; + let mut filter = None; + let mut groups = Vec::new(); + let mut window = None; - let group = if let Some("group") = parts.next() { + let mut next = parts.next(); + + if let Some(f) = next + && f != "group" + && f != "window" + { + let parsed_filter = + Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))?; + filter = Some(parsed_filter); + next = parts.next(); + } + + while let Some(g) = next + && g == "group" + { let group = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; - Some( - group - .parse() - .map_err(|_| RequestParserError::SyntaxError(1, group.to_owned()))?, - ) - } else { - None - }; + let parsed_group = group + .parse() + .map_err(|_| RequestParserError::SyntaxError(1, group.to_owned()))?; + groups.push(parsed_group); + next = parts.next(); + } + + if let Some(w) = next + && w == "window" + { + let window_str = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let parsed_window = window_str + .parse() + .map_err(|_| RequestParserError::SyntaxError(1, window_str.to_owned()))?; + window = Some(parsed_window); + } debug_assert!(parts.next().is_none()); - Ok((Request::List(tagname, filter, group), "")) + Ok((Request::List(tagname, filter, groups, window), "")) } fn parse_response( diff --git a/src/request.rs b/src/request.rs index 88cdf31..4019fc2 100644 --- a/src/request.rs +++ b/src/request.rs @@ -102,7 +102,7 @@ pub enum Request { Option, Option, ), - List(TagName, Filter, Option), + List(TagName, Option, Vec, Option), #[deprecated] ListAll(Option), #[deprecated]