From b1bbd4ebb10bc2284696d452e5929cc2d59ec275 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Mon, 8 Dec 2025 17:30:47 +0900 Subject: [PATCH] commands: use new error variants for a few more commands --- src/commands.rs | 11 ++++- src/commands/music_database/count.rs | 7 ++- src/commands/music_database/find.rs | 29 ++++++++++-- src/commands/music_database/findadd.rs | 37 +++++++++++---- src/commands/music_database/list.rs | 17 ++++++- src/commands/music_database/search.rs | 29 ++++++++++-- src/commands/music_database/searchadd.rs | 43 ++++++++++++++--- src/commands/music_database/searchaddpl.rs | 47 +++++++++++++++---- src/commands/music_database/searchcount.rs | 13 ++++- src/commands/queue/move_.rs | 21 ++++++--- src/commands/queue/moveid.rs | 16 +++++-- src/commands/queue/playlistfind.rs | 29 ++++++++++-- src/commands/queue/playlistsearch.rs | 29 ++++++++++-- src/commands/queue/plchanges.rs | 14 ++++-- src/commands/queue/plchangesposid.rs | 14 ++++-- src/commands/queue/prio.rs | 16 +++++-- src/commands/queue/prioid.rs | 11 +++-- src/commands/queue/rangeid.rs | 21 ++++++--- src/commands/queue/swap.rs | 16 +++++-- src/commands/queue/swapid.rs | 16 +++++-- src/commands/stickers/sticker_dec.rs | 8 +++- src/commands/stickers/sticker_find.rs | 29 ++++++++++-- src/commands/stickers/sticker_inc.rs | 8 +++- src/commands/stickers/sticker_set.rs | 2 +- src/commands/stored_playlists/listplaylist.rs | 2 +- .../stored_playlists/listplaylistinfo.rs | 2 +- src/commands/stored_playlists/playlistadd.rs | 6 ++- .../stored_playlists/playlistdelete.rs | 2 +- src/commands/stored_playlists/playlistmove.rs | 2 +- .../stored_playlists/searchplaylist.rs | 18 +++++-- 30 files changed, 413 insertions(+), 102 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index a9805146..36a9c931 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -612,10 +612,17 @@ pub enum RequestParserError { found: u32, }, - #[error("A keyword argument was provided without a value: {keyword}")] + #[error("Keyword argument {keyword} at position {argument_index} is missing its value")] MissingKeywordValue { /// The unexpected keyword that was found - keyword: String, + keyword: &'static str, + + /// The index of the argument that was missing it's value + /// + /// Note that in the case of keyworded arguments, such as + /// `group `, `sort `, etc., these are + /// counted as a single argument despite being two tokens. + argument_index: u32, }, #[error("A command list was expected to be closed, but the end was not found")] diff --git a/src/commands/music_database/count.rs b/src/commands/music_database/count.rs index a4dada76..da9fa92a 100644 --- a/src/commands/music_database/count.rs +++ b/src/commands/music_database/count.rs @@ -52,7 +52,12 @@ impl CommandRequest for CountRequest { }; let group = if let Some("group") = parts.next() { - let group = parts.next().ok_or(Self::missing_arguments_error(1))?; + let group = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + argument_index: 1, + keyword: "group", + })?; Some( group diff --git a/src/commands/music_database/find.rs b/src/commands/music_database/find.rs index a6365ce8..6ea02904 100644 --- a/src/commands/music_database/find.rs +++ b/src/commands/music_database/find.rs @@ -57,23 +57,44 @@ impl CommandRequest for FindRequest { None => return Err(Self::missing_arguments_error(0)), }; + let mut argument_index_counter = 0; let mut sort_or_window = parts.next(); let mut sort = None; if let Some("sort") = sort_or_window { - let s = parts.next().ok_or(Self::missing_arguments_error(1))?; + argument_index_counter += 1; + let s = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "sort", + argument_index: argument_index_counter, + })?; sort = Some( s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "Sort".to_string(), + raw_input: s.to_string(), + })?, ); sort_or_window = parts.next(); } let mut window = None; if let Some("window") = sort_or_window { - let w = parts.next().ok_or(Self::missing_arguments_error(2))?; + argument_index_counter += 1; + let w = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; window = Some( w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + })?, ); } diff --git a/src/commands/music_database/findadd.rs b/src/commands/music_database/findadd.rs index 93763bf4..86f6f2cf 100644 --- a/src/commands/music_database/findadd.rs +++ b/src/commands/music_database/findadd.rs @@ -61,16 +61,23 @@ impl CommandRequest for FindAddRequest { None => return Err(Self::missing_arguments_error(0)), }; + let mut argument_index_counter = 0; let mut sort_or_window_or_position = parts.next(); let mut sort = None; if let Some("sort") = sort_or_window_or_position { - let s = parts.next().ok_or(Self::missing_arguments_error(1))?; + argument_index_counter += 1; + let s = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "sort", + argument_index: argument_index_counter, + })?; sort = Some( s.parse() .map_err(|_| RequestParserError::SubtypeParserError { - argument_index: 1, + argument_index: argument_index_counter, expected_type: "Sort".to_string(), - raw_input: s.to_owned(), + raw_input: s.to_string(), })?, ); sort_or_window_or_position = parts.next(); @@ -78,13 +85,19 @@ impl CommandRequest for FindAddRequest { let mut window = None; if let Some("window") = sort_or_window_or_position { - let w = parts.next().ok_or(Self::missing_arguments_error(2))?; + argument_index_counter += 1; + let w = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; window = Some( w.parse() .map_err(|_| RequestParserError::SubtypeParserError { - argument_index: 2, + argument_index: argument_index_counter, expected_type: "WindowRange".to_string(), - raw_input: w.to_owned(), + raw_input: w.to_string(), })?, ); sort_or_window_or_position = parts.next(); @@ -92,13 +105,19 @@ impl CommandRequest for FindAddRequest { let mut position = None; if let Some("position") = sort_or_window_or_position { - let p = parts.next().ok_or(Self::missing_arguments_error(3))?; + argument_index_counter += 1; + let p = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "position", + argument_index: argument_index_counter, + })?; position = Some( p.parse() .map_err(|_| RequestParserError::SubtypeParserError { - argument_index: 3, + argument_index: argument_index_counter, expected_type: "SongPosition".to_string(), - raw_input: p.to_owned(), + raw_input: p.to_string(), })?, ); } diff --git a/src/commands/music_database/list.rs b/src/commands/music_database/list.rs index 19d8edd8..6e61af88 100644 --- a/src/commands/music_database/list.rs +++ b/src/commands/music_database/list.rs @@ -70,10 +70,12 @@ impl CommandRequest for ListRequest { let mut next = parts.next(); + let mut argument_index_counter = 0; if let Some(f) = next && f != "group" && f != "window" { + argument_index_counter += 1; let parsed_filter = Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))?; filter = Some(parsed_filter); @@ -83,7 +85,13 @@ impl CommandRequest for ListRequest { while let Some(g) = next && g == "group" { - let group = parts.next().ok_or(Self::missing_arguments_error(2))?; + argument_index_counter += 1; + let group = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "group", + argument_index: argument_index_counter, + })?; let parsed_group = group .parse() @@ -99,7 +107,12 @@ impl CommandRequest for ListRequest { if let Some(w) = next && w == "window" { - let window_str = parts.next().ok_or(Self::missing_arguments_error(3))?; + let window_str = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; let parsed_window = window_str .parse() diff --git a/src/commands/music_database/search.rs b/src/commands/music_database/search.rs index 3f643e2e..5882a079 100644 --- a/src/commands/music_database/search.rs +++ b/src/commands/music_database/search.rs @@ -57,23 +57,44 @@ impl CommandRequest for SearchRequest { None => return Err(Self::missing_arguments_error(0)), }; + let mut argument_index_counter = 0; let mut sort_or_window = parts.next(); let mut sort = None; if let Some("sort") = sort_or_window { - let s = parts.next().ok_or(Self::missing_arguments_error(1))?; + argument_index_counter += 1; + let s = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "sort", + argument_index: argument_index_counter, + })?; sort = Some( s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "Sort".to_string(), + raw_input: s.to_string(), + })?, ); sort_or_window = parts.next(); } let mut window = None; if let Some("window") = sort_or_window { - let w = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let w = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; window = Some( w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + })?, ); } diff --git a/src/commands/music_database/searchadd.rs b/src/commands/music_database/searchadd.rs index cbf6a7f4..336c3ec7 100644 --- a/src/commands/music_database/searchadd.rs +++ b/src/commands/music_database/searchadd.rs @@ -61,33 +61,64 @@ impl CommandRequest for SearchAddRequest { None => return Err(Self::missing_arguments_error(0)), }; + let mut argument_index_counter = 0; let mut sort_or_window_or_position = parts.next(); let mut sort = None; if let Some("sort") = sort_or_window_or_position { - let s = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let s = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "sort", + argument_index: argument_index_counter, + })?; sort = Some( s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "Sort".to_string(), + raw_input: s.to_string(), + })?, ); sort_or_window_or_position = parts.next(); } let mut window = None; if let Some("window") = sort_or_window_or_position { - let w = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let w = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; window = Some( w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + })?, ); sort_or_window_or_position = parts.next(); } let mut position = None; if let Some("position") = sort_or_window_or_position { - let p = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let p = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "position", + argument_index: argument_index_counter, + })?; position = Some( p.parse() - .map_err(|_| RequestParserError::SyntaxError(0, p.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "SongPosition".to_string(), + raw_input: p.to_string(), + })?, ); } diff --git a/src/commands/music_database/searchaddpl.rs b/src/commands/music_database/searchaddpl.rs index b4556f62..8104db81 100644 --- a/src/commands/music_database/searchaddpl.rs +++ b/src/commands/music_database/searchaddpl.rs @@ -66,43 +66,74 @@ impl CommandRequest for SearchAddPlRequest { fn parse(mut parts: RequestTokenizer<'_>) -> Result { let playlist_name = parts .next() - .ok_or(RequestParserError::UnexpectedEOF)? + .ok_or(Self::missing_arguments_error(0))? .to_string(); let filter = match parts.next() { Some(f) => { Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))? } - None => return Err(RequestParserError::UnexpectedEOF), + None => return Err(Self::missing_arguments_error(1)), }; + let mut argument_index_counter = 1; let mut sort_or_window_or_position = parts.next(); let mut sort = None; if let Some("sort") = sort_or_window_or_position { - let s = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let s = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "sort", + argument_index: argument_index_counter, + })?; sort = Some( s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "Sort".to_string(), + raw_input: s.to_string(), + })?, ); sort_or_window_or_position = parts.next(); } let mut window = None; if let Some("window") = sort_or_window_or_position { - let w = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let w = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; window = Some( w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + })?, ); sort_or_window_or_position = parts.next(); } let mut position = None; if let Some("position") = sort_or_window_or_position { - let p = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let p = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "position", + argument_index: argument_index_counter, + })?; position = Some( p.parse() - .map_err(|_| RequestParserError::SyntaxError(0, p.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "SongPosition".to_string(), + raw_input: p.to_string(), + })?, ); } diff --git a/src/commands/music_database/searchcount.rs b/src/commands/music_database/searchcount.rs index ab176d17..d0bce416 100644 --- a/src/commands/music_database/searchcount.rs +++ b/src/commands/music_database/searchcount.rs @@ -54,11 +54,20 @@ impl CommandRequest for SearchCountRequest { }; let group = if let Some("group") = parts.next() { - let group = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let group = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "group", + argument_index: 1, + })?; Some( group .parse() - .map_err(|_| RequestParserError::SyntaxError(1, group.to_owned()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "Group".to_string(), + raw_input: group.to_string(), + })?, ) } else { None diff --git a/src/commands/queue/move_.rs b/src/commands/queue/move_.rs index e3ae52e4..e6ffc360 100644 --- a/src/commands/queue/move_.rs +++ b/src/commands/queue/move_.rs @@ -35,15 +35,24 @@ impl CommandRequest for MoveRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let from_or_range = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; - let from_or_range = from_or_range - .parse() - .map_err(|_| RequestParserError::SyntaxError(0, from_or_range.to_string()))?; + let from_or_range = parts.next().ok_or(Self::missing_arguments_error(0))?; + let from_or_range = + from_or_range + .parse() + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "OneOrRange".to_string(), + raw_input: from_or_range.to_string(), + })?; - let to = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let to = parts.next().ok_or(Self::missing_arguments_error(1))?; let to = to .parse() - .map_err(|_| RequestParserError::SyntaxError(0, to.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "AbsoluteRelativeSongPosition".to_string(), + raw_input: to.to_string(), + })?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/queue/moveid.rs b/src/commands/queue/moveid.rs index 382f89d7..9dc4dc81 100644 --- a/src/commands/queue/moveid.rs +++ b/src/commands/queue/moveid.rs @@ -35,15 +35,23 @@ impl CommandRequest for MoveIdRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let id = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let id = parts.next().ok_or(Self::missing_arguments_error(0))?; let id = id .parse() - .map_err(|_| RequestParserError::SyntaxError(0, id.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "SongId".to_string(), + raw_input: id.to_string(), + })?; - let to = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let to = parts.next().ok_or(Self::missing_arguments_error(1))?; let to = to .parse() - .map_err(|_| RequestParserError::SyntaxError(0, to.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "AbsoluteRelativeSongPosition".to_string(), + raw_input: to.to_string(), + })?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/queue/playlistfind.rs b/src/commands/queue/playlistfind.rs index fb1f94a1..b05e716c 100644 --- a/src/commands/queue/playlistfind.rs +++ b/src/commands/queue/playlistfind.rs @@ -58,23 +58,44 @@ impl CommandRequest for PlaylistFindRequest { None => return Err(Self::missing_arguments_error(0)), }; + let mut argument_index_counter = 0; let mut sort_or_window = parts.next(); let mut sort = None; if let Some("sort") = sort_or_window { - let s = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let s = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "sort", + argument_index: argument_index_counter, + })?; sort = Some( s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "Sort".to_string(), + raw_input: s.to_string(), + })?, ); sort_or_window = parts.next(); } let mut window = None; if let Some("window") = sort_or_window { - let w = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let w = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; window = Some( w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + })?, ); } diff --git a/src/commands/queue/playlistsearch.rs b/src/commands/queue/playlistsearch.rs index 10ce3df2..93f25e23 100644 --- a/src/commands/queue/playlistsearch.rs +++ b/src/commands/queue/playlistsearch.rs @@ -57,23 +57,44 @@ impl CommandRequest for PlaylistSearchRequest { None => return Err(Self::missing_arguments_error(0)), }; + let mut argument_index_counter = 0; let mut sort_or_window = parts.next(); let mut sort = None; if let Some("sort") = sort_or_window { - let s = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let s = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "sort", + argument_index: argument_index_counter, + })?; sort = Some( s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "Sort".to_string(), + raw_input: s.to_string(), + })?, ); sort_or_window = parts.next(); } let mut window = None; if let Some("window") = sort_or_window { - let w = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let w = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; window = Some( w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + })?, ); } diff --git a/src/commands/queue/plchanges.rs b/src/commands/queue/plchanges.rs index 2d3788a9..aae816b9 100644 --- a/src/commands/queue/plchanges.rs +++ b/src/commands/queue/plchanges.rs @@ -41,16 +41,24 @@ impl CommandRequest for PlChangesRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let version = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let version = parts.next().ok_or(Self::missing_arguments_error(0))?; let version = version .parse() - .map_err(|_| RequestParserError::SyntaxError(0, version.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "PlaylistVersion".to_string(), + raw_input: version.to_string(), + })?; let window = parts .next() .map(|w| { w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string())) + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + }) }) .transpose()?; diff --git a/src/commands/queue/plchangesposid.rs b/src/commands/queue/plchangesposid.rs index fce82e86..f30d44bc 100644 --- a/src/commands/queue/plchangesposid.rs +++ b/src/commands/queue/plchangesposid.rs @@ -41,16 +41,24 @@ impl CommandRequest for PlChangesPosIdRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let version = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let version = parts.next().ok_or(Self::missing_arguments_error(0))?; let version = version .parse() - .map_err(|_| RequestParserError::SyntaxError(0, version.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "PlaylistVersion".to_string(), + raw_input: version.to_string(), + })?; let window = parts .next() .map(|w| { w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string())) + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + }) }) .transpose()?; diff --git a/src/commands/queue/prio.rs b/src/commands/queue/prio.rs index 4b7cec64..094f3202 100644 --- a/src/commands/queue/prio.rs +++ b/src/commands/queue/prio.rs @@ -35,15 +35,23 @@ impl CommandRequest for PrioRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let prio = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let prio = parts.next().ok_or(Self::missing_arguments_error(0))?; let prio = prio .parse() - .map_err(|_| RequestParserError::SyntaxError(0, prio.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "Priority".to_string(), + raw_input: prio.to_string(), + })?; - let window = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let window = parts.next().ok_or(Self::missing_arguments_error(1))?; let window = window .parse() - .map_err(|_| RequestParserError::SyntaxError(0, window.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "WindowRange".to_string(), + raw_input: window.to_string(), + })?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/queue/prioid.rs b/src/commands/queue/prioid.rs index 7930fc04..4eb259cd 100644 --- a/src/commands/queue/prioid.rs +++ b/src/commands/queue/prioid.rs @@ -42,12 +42,17 @@ impl CommandRequest for PrioIdRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let prio = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let prio = parts.next().ok_or(Self::missing_arguments_error(0))?; let prio = prio .parse() - .map_err(|_| RequestParserError::SyntaxError(0, prio.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "Priority".to_string(), + raw_input: prio.to_string(), + })?; - let songids = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + // TODO: determine how to count arguments here... + let songids = parts.next().ok_or(Self::missing_arguments_error(1))?; let songids = songids .split(',') .map(|s| { diff --git a/src/commands/queue/rangeid.rs b/src/commands/queue/rangeid.rs index eaa0a465..bf21e76b 100644 --- a/src/commands/queue/rangeid.rs +++ b/src/commands/queue/rangeid.rs @@ -38,15 +38,24 @@ impl CommandRequest for RangeIdRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let songid = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let songid = parts.next().ok_or(Self::missing_arguments_error(0))?; let songid = songid .parse() - .map_err(|_| RequestParserError::SyntaxError(0, songid.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "SongId".to_string(), + raw_input: songid.to_string(), + })?; - let time_interval = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; - let time_interval = time_interval - .parse() - .map_err(|_| RequestParserError::SyntaxError(0, time_interval.to_string()))?; + let time_interval = parts.next().ok_or(Self::missing_arguments_error(1))?; + let time_interval = + time_interval + .parse() + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "TimeInterval".to_string(), + raw_input: time_interval.to_string(), + })?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/queue/swap.rs b/src/commands/queue/swap.rs index 25357bbe..c2384b28 100644 --- a/src/commands/queue/swap.rs +++ b/src/commands/queue/swap.rs @@ -35,15 +35,23 @@ impl CommandRequest for SwapRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let songpos1 = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let songpos1 = parts.next().ok_or(Self::missing_arguments_error(0))?; let songpos1 = songpos1 .parse() - .map_err(|_| RequestParserError::SyntaxError(0, songpos1.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "SongPosition".to_string(), + raw_input: songpos1.to_string(), + })?; - let songpos2 = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let songpos2 = parts.next().ok_or(Self::missing_arguments_error(1))?; let songpos2 = songpos2 .parse() - .map_err(|_| RequestParserError::SyntaxError(0, songpos2.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "SongPosition".to_string(), + raw_input: songpos2.to_string(), + })?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/queue/swapid.rs b/src/commands/queue/swapid.rs index c23e22a2..125fdde4 100644 --- a/src/commands/queue/swapid.rs +++ b/src/commands/queue/swapid.rs @@ -35,15 +35,23 @@ impl CommandRequest for SwapIdRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let songid1 = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let songid1 = parts.next().ok_or(Self::missing_arguments_error(0))?; let songid1 = songid1 .parse() - .map_err(|_| RequestParserError::SyntaxError(0, songid1.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "SongId".to_string(), + raw_input: songid1.to_string(), + })?; - let songid2 = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let songid2 = parts.next().ok_or(Self::missing_arguments_error(1))?; let songid2 = songid2 .parse() - .map_err(|_| RequestParserError::SyntaxError(0, songid2.to_string()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 1, + expected_type: "SongId".to_string(), + raw_input: songid2.to_string(), + })?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/stickers/sticker_dec.rs b/src/commands/stickers/sticker_dec.rs index ea5b945c..2e550b01 100644 --- a/src/commands/stickers/sticker_dec.rs +++ b/src/commands/stickers/sticker_dec.rs @@ -77,10 +77,14 @@ impl CommandRequest for StickerDecRequest { raw_input: name.to_string(), })?; - let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let value = parts.next().ok_or(Self::missing_arguments_error(3))?; let value = value .parse() - .map_err(|_| RequestParserError::SyntaxError(1, value.to_owned()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 3, + expected_type: "usize".to_string(), + raw_input: value.to_string(), + })?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/stickers/sticker_find.rs b/src/commands/stickers/sticker_find.rs index 90fa2fe5..70834a33 100644 --- a/src/commands/stickers/sticker_find.rs +++ b/src/commands/stickers/sticker_find.rs @@ -95,23 +95,44 @@ impl CommandRequest for StickerFindRequest { raw_input: name.to_string(), })?; + let mut argument_index_counter = 2; let mut sort_or_window = parts.next(); let mut sort = None; if let Some("sort") = sort_or_window { - let s = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let s = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "sort", + argument_index: argument_index_counter, + })?; sort = Some( s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "Sort".to_string(), + raw_input: s.to_string(), + })?, ); sort_or_window = parts.next(); } let mut window = None; if let Some("window") = sort_or_window { - let w = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + argument_index_counter += 1; + let w = parts + .next() + .ok_or(RequestParserError::MissingKeywordValue { + keyword: "window", + argument_index: argument_index_counter, + })?; window = Some( w.parse() - .map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?, + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: argument_index_counter, + expected_type: "WindowRange".to_string(), + raw_input: w.to_string(), + })?, ); } diff --git a/src/commands/stickers/sticker_inc.rs b/src/commands/stickers/sticker_inc.rs index 0d087f36..db62d805 100644 --- a/src/commands/stickers/sticker_inc.rs +++ b/src/commands/stickers/sticker_inc.rs @@ -77,10 +77,14 @@ impl CommandRequest for StickerIncRequest { raw_input: name.to_string(), })?; - let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let value = parts.next().ok_or(Self::missing_arguments_error(3))?; let value = value .parse() - .map_err(|_| RequestParserError::SyntaxError(1, value.to_owned()))?; + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 3, + expected_type: "usize".to_string(), + raw_input: value.to_string(), + })?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/stickers/sticker_set.rs b/src/commands/stickers/sticker_set.rs index 1748dd59..29a56595 100644 --- a/src/commands/stickers/sticker_set.rs +++ b/src/commands/stickers/sticker_set.rs @@ -77,7 +77,7 @@ impl CommandRequest for StickerSetRequest { raw_input: name.to_string(), })?; - let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let value = parts.next().ok_or(Self::missing_arguments_error(3))?; Self::throw_if_too_many_arguments(parts)?; diff --git a/src/commands/stored_playlists/listplaylist.rs b/src/commands/stored_playlists/listplaylist.rs index 1dca9846..2b818f45 100644 --- a/src/commands/stored_playlists/listplaylist.rs +++ b/src/commands/stored_playlists/listplaylist.rs @@ -45,7 +45,7 @@ impl CommandRequest for ListPlaylistRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let name = parts.next().ok_or(Self::missing_arguments_error(0))?; let name = name .parse::() .map_err(|_| RequestParserError::SyntaxError(0, name.to_owned()))?; diff --git a/src/commands/stored_playlists/listplaylistinfo.rs b/src/commands/stored_playlists/listplaylistinfo.rs index a77ef5bc..4b3e1298 100644 --- a/src/commands/stored_playlists/listplaylistinfo.rs +++ b/src/commands/stored_playlists/listplaylistinfo.rs @@ -41,7 +41,7 @@ impl CommandRequest for ListPlaylistInfoRequest { } fn parse(mut parts: RequestTokenizer<'_>) -> Result { - let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let name = parts.next().ok_or(Self::missing_arguments_error(0))?; let name = name .parse::() .map_err(|_| RequestParserError::SyntaxError(0, name.to_owned()))?; diff --git a/src/commands/stored_playlists/playlistadd.rs b/src/commands/stored_playlists/playlistadd.rs index 1cb9ad02..0d956b6d 100644 --- a/src/commands/stored_playlists/playlistadd.rs +++ b/src/commands/stored_playlists/playlistadd.rs @@ -67,7 +67,11 @@ impl CommandRequest for PlaylistAddRequest { .next() .map(|s| { s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_owned())) + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 2, + expected_type: "SongPosition".to_string(), + raw_input: s.to_string(), + }) }) .transpose()?; diff --git a/src/commands/stored_playlists/playlistdelete.rs b/src/commands/stored_playlists/playlistdelete.rs index 7d92c23a..995b4a88 100644 --- a/src/commands/stored_playlists/playlistdelete.rs +++ b/src/commands/stored_playlists/playlistdelete.rs @@ -51,7 +51,7 @@ impl CommandRequest for PlaylistDeleteRequest { .to_string(); // TODO: this can be a range, according to docs - let position = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let position = parts.next().ok_or(Self::missing_arguments_error(1))?; let position = position .parse() .map_err(|_| RequestParserError::SyntaxError(0, position.to_string()))?; diff --git a/src/commands/stored_playlists/playlistmove.rs b/src/commands/stored_playlists/playlistmove.rs index 69057af8..e86e86d1 100644 --- a/src/commands/stored_playlists/playlistmove.rs +++ b/src/commands/stored_playlists/playlistmove.rs @@ -59,7 +59,7 @@ impl CommandRequest for PlaylistMoveRequest { .to_string(); let mut from = None; - let from_or_range_or_to = parts.next().ok_or(RequestParserError::UnexpectedEOF)?; + let from_or_range_or_to = parts.next().ok_or(Self::missing_arguments_error(1))?; let to = parts.next(); diff --git a/src/commands/stored_playlists/searchplaylist.rs b/src/commands/stored_playlists/searchplaylist.rs index c46763a1..0da87014 100644 --- a/src/commands/stored_playlists/searchplaylist.rs +++ b/src/commands/stored_playlists/searchplaylist.rs @@ -47,22 +47,30 @@ impl CommandRequest for SearchPlaylistRequest { fn parse(mut parts: RequestTokenizer<'_>) -> Result { let name = parts.next().ok_or(Self::missing_arguments_error(0))?; - let name = name - .parse::() - .map_err(|_| RequestParserError::SyntaxError(0, name.to_owned()))?; + let name = + name.parse::() + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "PlaylistName".to_string(), + raw_input: name.to_string(), + })?; let filter = match parts.next() { Some(f) => { Filter::parse(f).map_err(|_| RequestParserError::SyntaxError(1, f.to_owned()))? } - None => return Err(RequestParserError::UnexpectedEOF), + None => return Err(Self::missing_arguments_error(1)), }; let range = parts .next() .map(|s| { s.parse() - .map_err(|_| RequestParserError::SyntaxError(0, s.to_owned())) + .map_err(|_| RequestParserError::SubtypeParserError { + argument_index: 0, + expected_type: "WindowRange".to_string(), + raw_input: s.to_string(), + }) }) .transpose()?;