commands: use new error variants for various commands
Some checks failed
Build and test / build (push) Failing after 1m1s
Build and test / check (push) Failing after 1m25s
Build and test / test (push) Failing after 1m25s
Build and test / docs (push) Failing after 1m0s

This commit is contained in:
2025-12-08 15:54:37 +09:00
parent 2b3ab7389d
commit 3342293bf2
59 changed files with 653 additions and 296 deletions

View File

@@ -57,11 +57,40 @@ where
const COMMAND: &'static str;
// TODO: add these for ease of throwing parsing errors
// /// The minimum number of arguments this command takes
// const MIN_ARGS: u32;
/// The minimum number of arguments this command takes
const MIN_ARGS: u32;
// /// The maximum number of arguments this command takes
// const MAX_ARGS: Option<u32>;
/// The maximum number of arguments this command takes
const MAX_ARGS: Option<u32>;
/// Helper function to create a [`RequestParserError::TooManyArguments`] error
fn too_many_arguments_error(found: u32) -> RequestParserError {
RequestParserError::TooManyArguments {
expected_min: Self::MIN_ARGS,
expected_max: Self::MAX_ARGS,
found,
}
}
/// Helper function to throw a [`RequestParserError::TooManyArguments`] error
fn throw_if_too_many_arguments(parts: RequestTokenizer<'_>) -> Result<(), RequestParserError> {
let remaining_args = parts.count().try_into().unwrap_or(u32::MAX);
if remaining_args != 0 {
return Err(Self::too_many_arguments_error(
remaining_args.saturating_add(Self::MAX_ARGS.unwrap()),
));
}
Ok(())
}
/// Helper function to create a [`RequestParserError::MissingArguments`] error
fn missing_arguments_error(found: u32) -> RequestParserError {
RequestParserError::MissingArguments {
expected_min: Self::MIN_ARGS,
expected_max: Self::MAX_ARGS,
found,
}
}
/// Converts this specific request type to it's corresponding variant in the generic Request enum.
fn into_request_enum(self) -> crate::Request;
@@ -85,9 +114,11 @@ where
fn parse_raw(raw: &str) -> Result<Self, RequestParserError> {
let (line, rest) = raw
.split_once('\n')
.ok_or(RequestParserError::UnexpectedEOF)?;
.ok_or(RequestParserError::MissingNewline)?;
debug_assert!(rest.is_empty());
if line.is_empty() {
return Err(RequestParserError::EmptyLine);
}
let mut tokenized = RequestTokenizer::new(line);
@@ -239,6 +270,8 @@ macro_rules! empty_command_request {
impl crate::commands::CommandRequest for paste::paste! { [<$name Request>] } {
const COMMAND: &'static str = $command_name;
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = Some(0);
fn into_request_enum(self) -> crate::Request {
match Self::COMMAND {
@@ -261,19 +294,9 @@ macro_rules! empty_command_request {
}
fn parse(
mut parts: crate::commands::RequestTokenizer<'_>,
parts: crate::commands::RequestTokenizer<'_>,
) -> Result<Self, crate::commands::RequestParserError> {
if parts.next().is_some() {
return Err(crate::commands::RequestParserError::TooManyArguments {
expected_min: 0,
expected_max: 0,
found: parts
.count()
.try_into()
.unwrap_or(u32::MAX)
.saturating_add(1),
});
}
Self::throw_if_too_many_arguments(parts)?;
Ok(paste::paste! { [<$name Request>] })
}
@@ -316,6 +339,8 @@ macro_rules! single_item_command_request {
impl crate::commands::CommandRequest for paste::paste! { [<$name Request>] } {
const COMMAND: &'static str = $command_name;
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
match Self::COMMAND {
@@ -340,14 +365,7 @@ macro_rules! single_item_command_request {
fn parse(
mut parts: crate::commands::RequestTokenizer<'_>,
) -> Result<Self, crate::commands::RequestParserError> {
let item_token =
parts
.next()
.ok_or(crate::commands::RequestParserError::MissingArguments {
expected_min: 1,
expected_max: 1,
found: 0,
})?;
let item_token = parts.next().ok_or(Self::missing_arguments_error(0))?;
let item = item_token.parse::<$item_type>().map_err(|_| {
crate::commands::RequestParserError::SubtypeParserError {
@@ -357,17 +375,7 @@ macro_rules! single_item_command_request {
}
})?;
if parts.next().is_some() {
return Err(crate::commands::RequestParserError::TooManyArguments {
expected_min: 1,
expected_max: 1,
found: parts
.count()
.try_into()
.unwrap_or(u32::MAX)
.saturating_add(2),
});
}
Self::throw_if_too_many_arguments(parts)?;
Ok(paste::paste! { [<$name Request>] ( item ) })
}
@@ -384,6 +392,8 @@ macro_rules! single_optional_item_command_request {
impl crate::commands::CommandRequest for paste::paste! { [<$name Request>] } {
const COMMAND: &'static str = $command_name;
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
match Self::COMMAND {
@@ -424,18 +434,7 @@ macro_rules! single_optional_item_command_request {
})
.transpose()?;
if parts.next().is_some() {
let item_count = if item.is_some() { 1 } else { 0 };
return Err(crate::commands::RequestParserError::TooManyArguments {
expected_min: 0,
expected_max: 1,
found: parts
.count()
.try_into()
.unwrap_or(u32::MAX)
.saturating_add(item_count),
});
}
Self::throw_if_too_many_arguments(parts)?;
Ok(paste::paste! { [<$name Request>] ( item ) })
}
@@ -550,6 +549,7 @@ pub enum RequestParserError {
#[error("Could not parse the request due to a syntax error at position {0}: {1}")]
SyntaxError(u64, String),
// TODO: can we store the parser error as well?
#[error(
"Could not parse argument {argument_index} of the request (expected type: {expected_type}, raw input: '{raw_input}')"
)]
@@ -565,28 +565,32 @@ pub enum RequestParserError {
},
#[error(
"Too many arguments were provided in the request (expected between {expected_min} and {expected_max}, found {found})"
"Too many arguments were provided in the request (expected between {expected_min} and {expected_max:?}, found {found})"
)]
TooManyArguments {
/// The minimum number of arguments that were expected
expected_min: u32,
/// The maximum number of arguments that were expected
expected_max: u32,
///
/// This is `None` if the amount of arguments is unbounded.
expected_max: Option<u32>,
/// The number of arguments that were found
found: u32,
},
#[error(
"Not enough arguments were provided in the request (expected between {expected_min} and {expected_max}, found {found})"
"Not enough arguments were provided in the request (expected between {expected_min} and {expected_max:?}, found {found})"
)]
MissingArguments {
/// The minimum number of arguments that were expected
expected_min: u32,
/// The maximum number of arguments that were expected
expected_max: u32,
/// The maximum number of arguments that were expected.
///
/// This is `None` if the amount of arguments is unbounded.
expected_max: Option<u32>,
/// The number of arguments that were found
found: u32,
@@ -607,8 +611,9 @@ pub enum RequestParserError {
// TODO: remove this, replaced by EmptyLine + MissingArguments
#[error("Request ended early, while more arguments were expected")]
UnexpectedEOF,
// #[error("Request is missing terminating newline")]
// MissingNewline,
#[error("Request is missing terminating newline")]
MissingNewline,
}
// TODO: should these be renamed to fit the mpd docs?

View File

@@ -17,6 +17,8 @@ pub struct OutputSetRequest {
impl CommandRequest for OutputSetRequest {
const COMMAND: &'static str = "outputset";
const MIN_ARGS: u32 = 3;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::OutputSet(self.output_id, self.attribute_name, self.attribute_value)
@@ -46,14 +48,18 @@ impl CommandRequest for OutputSetRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let output_id = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let output_id = parts.next().ok_or(Self::missing_arguments_error(0))?;
let output_id = output_id
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, output_id.to_owned()))?;
let attribute_name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let attribute_value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "AudioOutputId".to_string(),
raw_input: output_id.to_string(),
})?;
let attribute_name = parts.next().ok_or(Self::missing_arguments_error(1))?;
let attribute_value = parts.next().ok_or(Self::missing_arguments_error(2))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(OutputSetRequest {
output_id,

View File

@@ -16,6 +16,8 @@ pub struct SendMessageRequest {
impl CommandRequest for SendMessageRequest {
const COMMAND: &'static str = "sendmessage";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::SendMessage(self.channel, self.message)
@@ -35,16 +37,18 @@ impl CommandRequest for SendMessageRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let channel = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let channel = parts.next().ok_or(Self::missing_arguments_error(0))?;
let channel = channel
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, channel.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "ChannelName".to_string(),
raw_input: channel.to_string(),
})?;
// TODO: SplitWhitespace::remainder() is unstable, use when stable
let message = parts.collect::<Vec<_>>().join(" ");
debug_assert!(!message.is_empty());
Ok(SendMessageRequest { channel, message })
}
}

View File

@@ -10,6 +10,8 @@ pub struct ProtocolDisableRequest(Vec<Feature>);
impl CommandRequest for ProtocolDisableRequest {
const COMMAND: &'static str = "protocol disable";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::ProtocolDisable(self.0)
@@ -35,16 +37,20 @@ impl CommandRequest for ProtocolDisableRequest {
fn parse(parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let mut parts = parts.peekable();
if parts.peek().is_none() {
return Err(RequestParserError::UnexpectedEOF);
return Err(Self::missing_arguments_error(0));
}
let mut features = Vec::with_capacity(parts.size_hint().0);
for part in parts {
let feature = part
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, part.to_owned()))?;
features.push(feature);
}
let features = parts
.enumerate()
.map(|(i, f)| {
f.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: i.try_into().unwrap_or(u32::MAX),
expected_type: "Feature".to_owned(),
raw_input: f.to_owned(),
})
})
.collect::<Result<Vec<Feature>, RequestParserError>>()?;
Ok(ProtocolDisableRequest(features))
}

View File

@@ -10,6 +10,8 @@ pub struct ProtocolEnableRequest(Vec<Feature>);
impl CommandRequest for ProtocolEnableRequest {
const COMMAND: &'static str = "protocol enable";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::ProtocolEnable(self.0)
@@ -35,16 +37,20 @@ impl CommandRequest for ProtocolEnableRequest {
fn parse(parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let mut parts = parts.peekable();
if parts.peek().is_none() {
return Err(RequestParserError::UnexpectedEOF);
return Err(Self::missing_arguments_error(0));
}
let mut features = Vec::with_capacity(parts.size_hint().0);
for part in parts {
let feature = part
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, part.to_owned()))?;
features.push(feature);
}
let features = parts
.enumerate()
.map(|(i, f)| {
f.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: i.try_into().unwrap_or(u32::MAX),
expected_type: "Feature".to_owned(),
raw_input: f.to_owned(),
})
})
.collect::<Result<Vec<Feature>, RequestParserError>>()?;
Ok(ProtocolEnableRequest(features))
}

View File

@@ -1,3 +1,5 @@
use std::u32;
use crate::{
commands::{Command, CommandRequest, RequestParserError, empty_command_response},
request_tokenizer::RequestTokenizer,
@@ -10,6 +12,8 @@ pub struct TagTypesDisableRequest(Vec<TagName>);
impl CommandRequest for TagTypesDisableRequest {
const COMMAND: &'static str = "tagtypes disable";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::TagTypesDisable(self.0)
@@ -37,13 +41,18 @@ impl CommandRequest for TagTypesDisableRequest {
fn parse(parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let mut parts = parts.peekable();
if parts.peek().is_none() {
return Err(RequestParserError::UnexpectedEOF);
return Err(Self::missing_arguments_error(0));
}
let tag_types = parts
.map(|s| {
.enumerate()
.map(|(i, s)| {
s.parse()
.map_err(|_| RequestParserError::SyntaxError(1, s.to_owned()))
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: i.try_into().unwrap_or(u32::MAX),
expected_type: "TagName".to_owned(),
raw_input: s.to_owned(),
})
})
.collect::<Result<Vec<TagName>, RequestParserError>>()?;

View File

@@ -10,6 +10,8 @@ pub struct TagTypesEnableRequest(Vec<TagName>);
impl CommandRequest for TagTypesEnableRequest {
const COMMAND: &'static str = "tagtypes enable";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::TagTypesEnable(self.0)
@@ -37,13 +39,18 @@ impl CommandRequest for TagTypesEnableRequest {
fn parse(parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let mut parts = parts.peekable();
if parts.peek().is_none() {
return Err(RequestParserError::UnexpectedEOF);
return Err(Self::missing_arguments_error(0));
}
let tag_types = parts
.map(|s| {
.enumerate()
.map(|(i, s)| {
s.parse()
.map_err(|_| RequestParserError::SyntaxError(1, s.to_owned()))
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: i.try_into().unwrap_or(u32::MAX),
expected_type: "TagName".to_owned(),
raw_input: s.to_owned(),
})
})
.collect::<Result<Vec<TagName>, RequestParserError>>()?;

View File

@@ -10,6 +10,8 @@ pub struct TagTypesResetRequest(Vec<TagName>);
impl CommandRequest for TagTypesResetRequest {
const COMMAND: &'static str = "tagtypes reset";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::TagTypesReset(self.0)
@@ -37,13 +39,18 @@ impl CommandRequest for TagTypesResetRequest {
fn parse(parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let mut parts = parts.peekable();
if parts.peek().is_none() {
return Err(RequestParserError::UnexpectedEOF);
return Err(Self::missing_arguments_error(0));
}
let tag_types = parts
.map(|s| {
.enumerate()
.map(|(i, s)| {
s.parse()
.map_err(|_| RequestParserError::SyntaxError(1, s.to_owned()))
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: i.try_into().unwrap_or(u32::MAX),
expected_type: "TagName".to_owned(),
raw_input: s.to_owned(),
})
})
.collect::<Result<Vec<TagName>, RequestParserError>>()?;

View File

@@ -9,6 +9,8 @@ pub struct PauseRequest(Option<bool>);
impl CommandRequest for PauseRequest {
const COMMAND: &'static str = "pause";
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::Pause(self.0)
@@ -33,11 +35,15 @@ impl CommandRequest for PauseRequest {
let result = match parts.next() {
Some("0") => Ok(Some(false)),
Some("1") => Ok(Some(true)),
Some(s) => Err(RequestParserError::SyntaxError(0, s.to_string())),
Some(s) => Err(RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "Option<bool>".to_owned(),
raw_input: s.to_owned(),
}),
None => Ok(None),
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
result.map(PauseRequest)
}

View File

@@ -16,6 +16,8 @@ pub struct SeekRequest {
impl CommandRequest for SeekRequest {
const COMMAND: &'static str = "seek";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::Seek(self.songpos, self.time)
@@ -34,20 +36,30 @@ impl CommandRequest for SeekRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let songpos = match parts.next() {
Some(s) => s
.parse::<SongPosition>()
.map_err(|_| RequestParserError::SyntaxError(0, s.to_owned()))?,
None => return Err(RequestParserError::UnexpectedEOF),
Some(s) => {
s.parse::<SongPosition>()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "SongPosition".to_string(),
raw_input: s.to_owned(),
})?
}
None => return Err(Self::missing_arguments_error(0)),
};
let time = match parts.next() {
Some(t) => t
.parse::<TimeWithFractions>()
.map_err(|_| RequestParserError::SyntaxError(0, t.to_owned()))?,
None => return Err(RequestParserError::UnexpectedEOF),
Some(t) => t.parse::<TimeWithFractions>().map_err(|_| {
RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "TimeWithFractions".to_string(),
raw_input: t.to_owned(),
}
})?,
None => return Err(Self::missing_arguments_error(1)),
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SeekRequest { songpos, time })
}

View File

@@ -16,6 +16,8 @@ pub struct SeekCurRequest {
impl CommandRequest for SeekCurRequest {
const COMMAND: &'static str = "seekcur";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::SeekCur(self.mode, self.time)
@@ -41,29 +43,42 @@ impl CommandRequest for SeekCurRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let time_raw = match parts.next() {
Some(t) => t,
None => return Err(RequestParserError::UnexpectedEOF),
None => return Err(Self::missing_arguments_error(0)),
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
// TODO: DRY
let (mode, time) = match time_raw {
t if t.starts_with('+') => (
SeekMode::Relative,
t[1..]
.parse::<TimeWithFractions>()
.map_err(|_| RequestParserError::SyntaxError(0, t.to_owned()))?,
t[1..].parse::<TimeWithFractions>().map_err(|_| {
RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "TimeWithFractions".to_string(),
raw_input: t[1..].to_owned(),
}
})?,
),
t if t.starts_with('-') => (
SeekMode::RelativeReverse,
t[1..]
.parse::<TimeWithFractions>()
.map_err(|_| RequestParserError::SyntaxError(0, t.to_owned()))?,
t[1..].parse::<TimeWithFractions>().map_err(|_| {
RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "TimeWithFractions".to_string(),
raw_input: t[1..].to_owned(),
}
})?,
),
t => (
SeekMode::Absolute,
t.parse::<TimeWithFractions>()
.map_err(|_| RequestParserError::SyntaxError(0, t.to_owned()))?,
t.parse::<TimeWithFractions>().map_err(|_| {
RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "TimeWithFractions".to_string(),
raw_input: t.to_owned(),
}
})?,
),
};

View File

@@ -16,6 +16,8 @@ pub struct SeekIdRequest {
impl CommandRequest for SeekIdRequest {
const COMMAND: &'static str = "seekid";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::SeekId(self.songid, self.time)
@@ -36,18 +38,26 @@ impl CommandRequest for SeekIdRequest {
let songid = match parts.next() {
Some(s) => s
.parse::<SongId>()
.map_err(|_| RequestParserError::SyntaxError(0, s.to_owned()))?,
None => return Err(RequestParserError::UnexpectedEOF),
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "SongId".to_string(),
raw_input: s.to_owned(),
})?,
None => return Err(Self::missing_arguments_error(0)),
};
let time = match parts.next() {
Some(t) => t
.parse::<TimeWithFractions>()
.map_err(|_| RequestParserError::SyntaxError(0, t.to_owned()))?,
None => return Err(RequestParserError::UnexpectedEOF),
Some(t) => t.parse::<TimeWithFractions>().map_err(|_| {
RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "TimeWithFractions".to_string(),
raw_input: t.to_owned(),
}
})?,
None => return Err(Self::missing_arguments_error(1)),
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SeekIdRequest { songid, time })
}

View File

@@ -16,6 +16,8 @@ pub struct MountRequest {
impl CommandRequest for MountRequest {
const COMMAND: &'static str = "mount";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::Mount(self.path, self.uri)
@@ -39,17 +41,21 @@ impl CommandRequest for MountRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let path = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let path = parts.next().ok_or(Self::missing_arguments_error(0))?;
let path = path
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, path.to_string()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "MountPath".to_string(),
raw_input: path.to_string(),
})?;
let uri = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(1))?
.to_string();
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(MountRequest { path, uri })
}

View File

@@ -12,6 +12,8 @@ pub struct UnmountRequest(MountPath);
impl CommandRequest for UnmountRequest {
const COMMAND: &'static str = "unmount";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::Unmount(self.0)
@@ -34,14 +36,18 @@ impl CommandRequest for UnmountRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let item_token = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let item = item_token
.parse::<MountPath>()
.map_err(|_| RequestParserError::SyntaxError(0, item_token.to_owned()))?;
let path = parts.next().ok_or(Self::missing_arguments_error(0))?;
let path =
path.parse::<MountPath>()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "MountPath".to_string(),
raw_input: path.to_string(),
})?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(UnmountRequest(item))
Ok(UnmountRequest(path))
}
}

View File

@@ -19,6 +19,8 @@ pub struct AlbumArtRequest {
impl CommandRequest for AlbumArtRequest {
const COMMAND: &'static str = "albumart";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::AlbumArt(self.uri, self.offset)
@@ -38,17 +40,21 @@ impl CommandRequest for AlbumArtRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let uri = match parts.next() {
Some(s) => s,
None => return Err(RequestParserError::UnexpectedEOF),
None => return Err(Self::missing_arguments_error(0)),
};
let offset = match parts.next() {
Some(s) => s
.parse::<Offset>()
.map_err(|_| RequestParserError::SyntaxError(1, s.to_owned()))?,
None => return Err(RequestParserError::UnexpectedEOF),
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Offset".to_string(),
raw_input: s.to_string(),
})?,
None => return Err(Self::missing_arguments_error(1)),
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(AlbumArtRequest {
uri: uri.to_string(),

View File

@@ -20,6 +20,8 @@ pub struct CountRequest {
impl CommandRequest for CountRequest {
const COMMAND: &'static str = "count";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::Count(self.filter, self.group)
@@ -46,22 +48,26 @@ impl CommandRequest for CountRequest {
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(0)),
};
let group = if let Some("group") = parts.next() {
let group = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let group = parts.next().ok_or(Self::missing_arguments_error(1))?;
Some(
group
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, group.to_owned()))?,
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "GroupType".to_string(),
raw_input: group.to_owned(),
})?,
)
} else {
None
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(CountRequest { filter, group })
}

View File

@@ -19,6 +19,8 @@ pub struct FindRequest {
impl CommandRequest for FindRequest {
const COMMAND: &'static str = "find";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::Find(self.filter, self.sort, self.window)
@@ -52,13 +54,13 @@ impl CommandRequest for FindRequest {
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(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)?;
let s = parts.next().ok_or(Self::missing_arguments_error(1))?;
sort = Some(
s.parse()
.map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?,
@@ -68,14 +70,14 @@ impl CommandRequest for FindRequest {
let mut window = None;
if let Some("window") = sort_or_window {
let w = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let w = parts.next().ok_or(Self::missing_arguments_error(2))?;
window = Some(
w.parse()
.map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?,
);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(FindRequest {
filter,

View File

@@ -19,6 +19,8 @@ pub struct FindAddRequest {
impl CommandRequest for FindAddRequest {
const COMMAND: &'static str = "findadd";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(4);
fn into_request_enum(self) -> crate::Request {
crate::Request::FindAdd(self.filter, self.sort, self.window, self.position)
@@ -56,40 +58,52 @@ impl CommandRequest for FindAddRequest {
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(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)?;
let s = parts.next().ok_or(Self::missing_arguments_error(1))?;
sort = Some(
s.parse()
.map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?,
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Sort".to_string(),
raw_input: s.to_owned(),
})?,
);
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)?;
let w = parts.next().ok_or(Self::missing_arguments_error(2))?;
window = Some(
w.parse()
.map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?,
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "WindowRange".to_string(),
raw_input: w.to_owned(),
})?,
);
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)?;
let p = parts.next().ok_or(Self::missing_arguments_error(3))?;
position = Some(
p.parse()
.map_err(|_| RequestParserError::SyntaxError(0, p.to_string()))?,
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 3,
expected_type: "SongPosition".to_string(),
raw_input: p.to_owned(),
})?,
);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(FindAddRequest {
filter,

View File

@@ -20,6 +20,8 @@ pub struct ListRequest {
impl CommandRequest for ListRequest {
const COMMAND: &'static str = "list";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::List(self.tagname, self.filter, self.groups, self.window)
@@ -53,10 +55,14 @@ impl CommandRequest for ListRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let tagname = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let tagname = parts.next().ok_or(Self::missing_arguments_error(0))?;
let tagname = tagname
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, tagname.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "TagName".to_string(),
raw_input: tagname.to_owned(),
})?;
let mut filter = None;
let mut groups = Vec::new();
@@ -77,10 +83,15 @@ impl CommandRequest for ListRequest {
while let Some(g) = next
&& g == "group"
{
let group = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let parsed_group = group
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, group.to_owned()))?;
let group = parts.next().ok_or(Self::missing_arguments_error(2))?;
let parsed_group =
group
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "GroupType".to_string(),
raw_input: group.to_owned(),
})?;
groups.push(parsed_group);
next = parts.next();
}
@@ -88,14 +99,19 @@ impl CommandRequest for ListRequest {
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()))?;
let window_str = parts.next().ok_or(Self::missing_arguments_error(3))?;
let parsed_window =
window_str
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 3,
expected_type: "WindowRange".to_string(),
raw_input: window_str.to_owned(),
})?;
window = Some(parsed_window);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(ListRequest {
tagname,

View File

@@ -21,6 +21,8 @@ pub struct ReadPictureRequest {
impl CommandRequest for ReadPictureRequest {
const COMMAND: &'static str = "readpicture";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::ReadPicture(self.uri, self.offset)
@@ -40,17 +42,21 @@ impl CommandRequest for ReadPictureRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let uri = match parts.next() {
Some(s) => s,
None => return Err(RequestParserError::UnexpectedEOF),
None => return Err(Self::missing_arguments_error(0)),
};
let offset = match parts.next() {
Some(s) => s
.parse::<Offset>()
.map_err(|_| RequestParserError::SyntaxError(1, s.to_owned()))?,
None => return Err(RequestParserError::UnexpectedEOF),
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Offset".to_string(),
raw_input: s.to_owned(),
})?,
None => return Err(Self::missing_arguments_error(1)),
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(ReadPictureRequest {
uri: uri.to_string(),

View File

@@ -19,6 +19,8 @@ pub struct SearchRequest {
impl CommandRequest for SearchRequest {
const COMMAND: &'static str = "search";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::Search(self.filter, self.sort, self.window)
@@ -52,13 +54,13 @@ impl CommandRequest for SearchRequest {
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(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)?;
let s = parts.next().ok_or(Self::missing_arguments_error(1))?;
sort = Some(
s.parse()
.map_err(|_| RequestParserError::SyntaxError(0, s.to_string()))?,
@@ -75,7 +77,7 @@ impl CommandRequest for SearchRequest {
);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SearchRequest {
filter,

View File

@@ -19,6 +19,8 @@ pub struct SearchAddRequest {
impl CommandRequest for SearchAddRequest {
const COMMAND: &'static str = "searchadd";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(4);
fn into_request_enum(self) -> crate::Request {
crate::Request::SearchAdd(self.filter, self.sort, self.window, self.position)
@@ -56,7 +58,7 @@ impl CommandRequest for SearchAddRequest {
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(0)),
};
let mut sort_or_window_or_position = parts.next();
@@ -89,7 +91,7 @@ impl CommandRequest for SearchAddRequest {
);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SearchAddRequest {
filter,

View File

@@ -20,6 +20,8 @@ pub struct SearchAddPlRequest {
impl CommandRequest for SearchAddPlRequest {
const COMMAND: &'static str = "searchaddpl";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(5);
fn into_request_enum(self) -> crate::Request {
crate::Request::SearchAddPl(
@@ -104,7 +106,7 @@ impl CommandRequest for SearchAddPlRequest {
);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SearchAddPlRequest {
playlist_name,

View File

@@ -20,6 +20,8 @@ pub struct SearchCountRequest {
impl CommandRequest for SearchCountRequest {
const COMMAND: &'static str = "searchcount";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::SearchCount(self.filter, self.group)
@@ -48,7 +50,7 @@ impl CommandRequest for SearchCountRequest {
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(0)),
};
let group = if let Some("group") = parts.next() {
@@ -62,7 +64,7 @@ impl CommandRequest for SearchCountRequest {
None
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SearchCountRequest { filter, group })
}

View File

@@ -9,6 +9,8 @@ pub struct RandomRequest(bool);
impl CommandRequest for RandomRequest {
const COMMAND: &'static str = "random";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::Random(self.0)
@@ -30,11 +32,17 @@ impl CommandRequest for RandomRequest {
let state = match parts.next() {
Some("0") => false,
Some("1") => true,
Some(s) => return Err(RequestParserError::SyntaxError(0, s.to_owned())),
None => return Err(RequestParserError::UnexpectedEOF),
Some(s) => {
return Err(RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "bool".to_owned(),
raw_input: s.to_owned(),
});
}
None => return Err(Self::missing_arguments_error(0)),
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(RandomRequest(state))
}

View File

@@ -9,6 +9,8 @@ pub struct RepeatRequest(bool);
impl CommandRequest for RepeatRequest {
const COMMAND: &'static str = "repeat";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::Repeat(self.0)
@@ -30,11 +32,17 @@ impl CommandRequest for RepeatRequest {
let state = match parts.next() {
Some("0") => false,
Some("1") => true,
Some(s) => return Err(RequestParserError::SyntaxError(0, s.to_owned())),
None => return Err(RequestParserError::UnexpectedEOF),
Some(s) => {
return Err(RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "bool".to_owned(),
raw_input: s.to_owned(),
});
}
None => return Err(Self::missing_arguments_error(0)),
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(RepeatRequest(state))
}

View File

@@ -12,6 +12,8 @@ pub struct IdleRequest(Option<Vec<SubSystem>>);
impl CommandRequest for IdleRequest {
const COMMAND: &'static str = "idle";
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::Idle(self.0)
@@ -48,8 +50,6 @@ impl CommandRequest for IdleRequest {
Ok(Some(subsystems))
});
debug_assert!(parts.next().is_none());
result.map(IdleRequest)
}
}

View File

@@ -16,6 +16,8 @@ pub struct AddRequest {
impl CommandRequest for AddRequest {
const COMMAND: &'static str = "add";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::Add(self.uri, self.position)
@@ -38,18 +40,21 @@ impl CommandRequest for AddRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let uri = match parts.next() {
Some(s) => s,
None => return Err(RequestParserError::UnexpectedEOF),
None => return Err(Self::missing_arguments_error(0)),
};
let position = match parts.next() {
Some(s) => Some(
s.parse::<SongPosition>()
.map_err(|_| RequestParserError::SyntaxError(1, s.to_owned()))?,
),
Some(s) => Some(s.parse::<SongPosition>().map_err(|_| {
RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "SongPosition".to_string(),
raw_input: s.to_owned(),
}
})?),
None => None,
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(AddRequest {
uri: uri.to_string(),

View File

@@ -17,6 +17,8 @@ pub struct AddIdRequest {
impl CommandRequest for AddIdRequest {
const COMMAND: &'static str = "addid";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::AddId(self.uri, self.position)
@@ -39,18 +41,21 @@ impl CommandRequest for AddIdRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let uri = match parts.next() {
Some(s) => s,
None => return Err(RequestParserError::UnexpectedEOF),
None => return Err(Self::missing_arguments_error(0)),
};
let position = match parts.next() {
Some(s) => Some(
s.parse::<SongPosition>()
.map_err(|_| RequestParserError::SyntaxError(1, s.to_owned()))?,
),
Some(s) => Some(s.parse::<SongPosition>().map_err(|_| {
RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "SongPosition".to_string(),
raw_input: s.to_owned(),
}
})?),
None => None,
};
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(AddIdRequest {
uri: uri.to_string(),

View File

@@ -17,6 +17,8 @@ pub struct AddTagIdRequest {
impl CommandRequest for AddTagIdRequest {
const COMMAND: &'static str = "addtagid";
const MIN_ARGS: u32 = 3;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::AddTagId(self.songid, self.tag_name, self.tag_value)
@@ -44,22 +46,34 @@ impl CommandRequest for AddTagIdRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
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_owned(),
})?;
let tag_name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let tag_name = parts.next().ok_or(Self::missing_arguments_error(1))?;
let tag_name = tag_name
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, tag_name.to_string()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "TagName".to_string(),
raw_input: tag_name.to_owned(),
})?;
let tag_value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let tag_value = parts.next().ok_or(Self::missing_arguments_error(2))?;
let tag_value = tag_value
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, tag_value.to_string()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "TagValue".to_string(),
raw_input: tag_value.to_owned(),
})?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(AddTagIdRequest {
songid,

View File

@@ -16,6 +16,8 @@ pub struct ClearTagIdRequest {
impl CommandRequest for ClearTagIdRequest {
const COMMAND: &'static str = "cleartagid";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::ClearTagId(self.songid, self.tag_name)
@@ -35,17 +37,25 @@ impl CommandRequest for ClearTagIdRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
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 tag_name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let tag_name = parts.next().ok_or(Self::missing_arguments_error(1))?;
let tag_name = tag_name
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, tag_name.to_string()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "TagName".to_string(),
raw_input: tag_name.to_string(),
})?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(ClearTagIdRequest { songid, tag_name })
}

View File

@@ -16,6 +16,8 @@ pub struct MoveRequest {
impl CommandRequest for MoveRequest {
const COMMAND: &'static str = "move";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::Move(self.from_or_range, self.to)
@@ -43,7 +45,7 @@ impl CommandRequest for MoveRequest {
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, to.to_string()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(MoveRequest { from_or_range, to })
}

View File

@@ -16,6 +16,8 @@ pub struct MoveIdRequest {
impl CommandRequest for MoveIdRequest {
const COMMAND: &'static str = "moveid";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::MoveId(self.id, self.to)
@@ -43,7 +45,7 @@ impl CommandRequest for MoveIdRequest {
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, to.to_string()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(MoveIdRequest { id, to })
}

View File

@@ -20,6 +20,8 @@ pub struct PlaylistFindRequest {
impl CommandRequest for PlaylistFindRequest {
const COMMAND: &'static str = "playlistfind";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::PlaylistFind(self.filter, self.sort, self.window)
@@ -53,7 +55,7 @@ impl CommandRequest for PlaylistFindRequest {
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(0)),
};
let mut sort_or_window = parts.next();
@@ -76,7 +78,7 @@ impl CommandRequest for PlaylistFindRequest {
);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(PlaylistFindRequest {
filter,

View File

@@ -19,6 +19,8 @@ pub struct PlaylistSearchRequest {
impl CommandRequest for PlaylistSearchRequest {
const COMMAND: &'static str = "playlistsearch";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::PlaylistSearch(self.filter, self.sort, self.window)
@@ -52,7 +54,7 @@ impl CommandRequest for PlaylistSearchRequest {
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(0)),
};
let mut sort_or_window = parts.next();
@@ -75,7 +77,7 @@ impl CommandRequest for PlaylistSearchRequest {
);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(PlaylistSearchRequest {
filter,

View File

@@ -17,6 +17,8 @@ pub struct PlChangesRequest {
impl CommandRequest for PlChangesRequest {
const COMMAND: &'static str = "plchanges";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::PlChanges(self.version, self.window)
@@ -52,7 +54,7 @@ impl CommandRequest for PlChangesRequest {
})
.transpose()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(PlChangesRequest { version, window })
}

View File

@@ -17,6 +17,8 @@ pub struct PlChangesPosIdRequest {
impl CommandRequest for PlChangesPosIdRequest {
const COMMAND: &'static str = "plchangesposid";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::PlChangesPosId(self.version, self.window)
@@ -52,7 +54,7 @@ impl CommandRequest for PlChangesPosIdRequest {
})
.transpose()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(PlChangesPosIdRequest { version, window })
}

View File

@@ -16,6 +16,8 @@ pub struct PrioRequest {
impl CommandRequest for PrioRequest {
const COMMAND: &'static str = "prio";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::Prio(self.prio, self.window)
@@ -43,7 +45,7 @@ impl CommandRequest for PrioRequest {
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, window.to_string()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(PrioRequest { prio, window })
}

View File

@@ -16,6 +16,9 @@ pub struct PrioIdRequest {
impl CommandRequest for PrioIdRequest {
const COMMAND: &'static str = "prioid";
const MIN_ARGS: u32 = 2;
// TODO: should this be 2?
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::PrioId(self.prio, self.songids)
@@ -53,7 +56,7 @@ impl CommandRequest for PrioIdRequest {
})
.collect::<Result<Vec<SongId>, RequestParserError>>()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(PrioIdRequest { prio, songids })
}

View File

@@ -16,6 +16,8 @@ pub struct RangeIdRequest {
impl CommandRequest for RangeIdRequest {
const COMMAND: &'static str = "rangeid";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::RangeId(self.songid, self.time_interval)
@@ -46,7 +48,7 @@ impl CommandRequest for RangeIdRequest {
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, time_interval.to_string()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(RangeIdRequest {
songid,

View File

@@ -16,6 +16,8 @@ pub struct SwapRequest {
impl CommandRequest for SwapRequest {
const COMMAND: &'static str = "swap";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::Swap(self.songpos1, self.songpos2)
@@ -43,7 +45,7 @@ impl CommandRequest for SwapRequest {
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, songpos2.to_string()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SwapRequest { songpos1, songpos2 })
}

View File

@@ -16,6 +16,8 @@ pub struct SwapIdRequest {
impl CommandRequest for SwapIdRequest {
const COMMAND: &'static str = "swapid";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::SwapId(self.songid1, self.songid2)
@@ -43,7 +45,7 @@ impl CommandRequest for SwapIdRequest {
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, songid2.to_string()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SwapIdRequest { songid1, songid2 })
}

View File

@@ -18,6 +18,8 @@ pub struct StickerDecRequest {
impl CommandRequest for StickerDecRequest {
const COMMAND: &'static str = "sticker dec";
const MIN_ARGS: u32 = 4;
const MAX_ARGS: Option<u32> = Some(4);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerDec(self.sticker_type, self.uri, self.name, self.value)
@@ -47,27 +49,40 @@ impl CommandRequest for StickerDecRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let sticker_type = sticker_type
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
let sticker_type = parts.next().ok_or(Self::missing_arguments_error(0))?;
let sticker_type =
sticker_type
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "StickerType".to_string(),
raw_input: sticker_type.to_string(),
})?;
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let uri = parts.next().ok_or(Self::missing_arguments_error(1))?;
let uri = uri
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Uri".to_string(),
raw_input: uri.to_string(),
})?;
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let name = parts.next().ok_or(Self::missing_arguments_error(2))?;
let name = name
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "String".to_string(),
raw_input: name.to_string(),
})?;
let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let value = value
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, value.to_owned()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(StickerDecRequest {
sticker_type,

View File

@@ -17,6 +17,8 @@ pub struct StickerDeleteRequest {
impl CommandRequest for StickerDeleteRequest {
const COMMAND: &'static str = "sticker delete";
const MIN_ARGS: u32 = 3;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerDelete(self.sticker_type, self.uri, self.name)
@@ -44,22 +46,35 @@ impl CommandRequest for StickerDeleteRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let sticker_type = sticker_type
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
let sticker_type = parts.next().ok_or(Self::missing_arguments_error(0))?;
let sticker_type =
sticker_type
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "StickerType".to_string(),
raw_input: sticker_type.to_string(),
})?;
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let uri = parts.next().ok_or(Self::missing_arguments_error(1))?;
let uri = uri
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Uri".to_string(),
raw_input: uri.to_string(),
})?;
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let name = parts.next().ok_or(Self::missing_arguments_error(2))?;
let name = name
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "String".to_string(),
raw_input: name.to_string(),
})?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(StickerDeleteRequest {
sticker_type,

View File

@@ -20,6 +20,8 @@ pub struct StickerFindRequest {
impl CommandRequest for StickerFindRequest {
const COMMAND: &'static str = "sticker find";
const MIN_ARGS: u32 = 3;
const MAX_ARGS: Option<u32> = Some(5);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerFind(
@@ -65,20 +67,33 @@ impl CommandRequest for StickerFindRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let sticker_type = sticker_type
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
let sticker_type = parts.next().ok_or(Self::missing_arguments_error(0))?;
let sticker_type =
sticker_type
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "StickerType".to_string(),
raw_input: sticker_type.to_string(),
})?;
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let uri = parts.next().ok_or(Self::missing_arguments_error(1))?;
let uri = uri
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Uri".to_string(),
raw_input: uri.to_string(),
})?;
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let name = parts.next().ok_or(Self::missing_arguments_error(2))?;
let name = name
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "String".to_string(),
raw_input: name.to_string(),
})?;
let mut sort_or_window = parts.next();
let mut sort = None;
@@ -100,7 +115,7 @@ impl CommandRequest for StickerFindRequest {
);
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(StickerFindRequest {
sticker_type,

View File

@@ -17,6 +17,8 @@ pub struct StickerGetRequest {
impl CommandRequest for StickerGetRequest {
const COMMAND: &'static str = "sticker get";
const MIN_ARGS: u32 = 3;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerGet(self.sticker_type, self.uri, self.name)
@@ -44,22 +46,35 @@ impl CommandRequest for StickerGetRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let sticker_type = sticker_type
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
let sticker_type = parts.next().ok_or(Self::missing_arguments_error(0))?;
let sticker_type =
sticker_type
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "StickerType".to_string(),
raw_input: sticker_type.to_string(),
})?;
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let uri = parts.next().ok_or(Self::missing_arguments_error(1))?;
let uri = uri
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Uri".to_string(),
raw_input: uri.to_string(),
})?;
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let name = parts.next().ok_or(Self::missing_arguments_error(2))?;
let name = name
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "String".to_string(),
raw_input: name.to_string(),
})?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(StickerGetRequest {
sticker_type,

View File

@@ -18,6 +18,8 @@ pub struct StickerIncRequest {
impl CommandRequest for StickerIncRequest {
const COMMAND: &'static str = "sticker inc";
const MIN_ARGS: u32 = 4;
const MAX_ARGS: Option<u32> = Some(4);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerInc(self.sticker_type, self.uri, self.name, self.value)
@@ -47,27 +49,40 @@ impl CommandRequest for StickerIncRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let sticker_type = sticker_type
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
let sticker_type = parts.next().ok_or(Self::missing_arguments_error(0))?;
let sticker_type =
sticker_type
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "StickerType".to_string(),
raw_input: sticker_type.to_string(),
})?;
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let uri = parts.next().ok_or(Self::missing_arguments_error(1))?;
let uri = uri
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Uri".to_string(),
raw_input: uri.to_string(),
})?;
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let name = parts.next().ok_or(Self::missing_arguments_error(2))?;
let name = name
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "String".to_string(),
raw_input: name.to_string(),
})?;
let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let value = value
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, value.to_owned()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(StickerIncRequest {
sticker_type,

View File

@@ -19,6 +19,8 @@ pub struct StickerListRequest {
impl CommandRequest for StickerListRequest {
const COMMAND: &'static str = "sticker list";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerList(self.sticker_type, self.uri)
@@ -38,17 +40,26 @@ impl CommandRequest for StickerListRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let sticker_type = sticker_type
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
let sticker_type = parts.next().ok_or(Self::missing_arguments_error(0))?;
let sticker_type =
sticker_type
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "StickerType".to_string(),
raw_input: sticker_type.to_string(),
})?;
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let uri = parts.next().ok_or(Self::missing_arguments_error(1))?;
let uri = uri
.parse()
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Uri".to_string(),
raw_input: uri.to_string(),
})?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(StickerListRequest { sticker_type, uri })
}

View File

@@ -18,6 +18,8 @@ pub struct StickerSetRequest {
impl CommandRequest for StickerSetRequest {
const COMMAND: &'static str = "sticker set";
const MIN_ARGS: u32 = 4;
const MAX_ARGS: Option<u32> = Some(4);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerSet(self.sticker_type, self.uri, self.name, self.value)
@@ -47,24 +49,37 @@ impl CommandRequest for StickerSetRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let sticker_type = sticker_type
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, sticker_type.to_owned()))?;
let sticker_type = parts.next().ok_or(Self::missing_arguments_error(0))?;
let sticker_type =
sticker_type
.parse()
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 0,
expected_type: "StickerType".to_string(),
raw_input: sticker_type.to_string(),
})?;
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let uri = parts.next().ok_or(Self::missing_arguments_error(1))?;
let uri = uri
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, uri.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 1,
expected_type: "Uri".to_string(),
raw_input: uri.to_string(),
})?;
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let name = parts.next().ok_or(Self::missing_arguments_error(2))?;
let name = name
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, name.to_owned()))?;
.map_err(|_| RequestParserError::SubtypeParserError {
argument_index: 2,
expected_type: "String".to_string(),
raw_input: name.to_string(),
})?;
let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(StickerSetRequest {
sticker_type,

View File

@@ -16,6 +16,8 @@ pub struct StickerNamesTypesRequest(Option<StickerType>);
impl CommandRequest for StickerNamesTypesRequest {
const COMMAND: &'static str = "stickernamestypes";
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerNamesTypes(self.0)
@@ -48,7 +50,7 @@ impl CommandRequest for StickerNamesTypesRequest {
})
.transpose()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(StickerNamesTypesRequest(sticker_type))
}

View File

@@ -22,6 +22,8 @@ pub struct ListPlaylistRequest {
impl CommandRequest for ListPlaylistRequest {
const COMMAND: &'static str = "listplaylist";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::ListPlaylist(self.name, self.range)
@@ -56,7 +58,7 @@ impl CommandRequest for ListPlaylistRequest {
})
.transpose()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(ListPlaylistRequest { name, range })
}

View File

@@ -17,6 +17,8 @@ pub struct ListPlaylistInfoRequest {
impl CommandRequest for ListPlaylistInfoRequest {
const COMMAND: &'static str = "listplaylistinfo";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::ListPlaylistInfo(self.name, self.range)
@@ -52,7 +54,7 @@ impl CommandRequest for ListPlaylistInfoRequest {
})
.transpose()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(ListPlaylistInfoRequest { name, range })
}

View File

@@ -17,6 +17,8 @@ pub struct LoadRequest {
impl CommandRequest for LoadRequest {
const COMMAND: &'static str = "load";
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::Load(self.name, self.range, self.position)
@@ -53,7 +55,7 @@ impl CommandRequest for LoadRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let playlist_name = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(0))?
.to_string();
let mut range = None;
@@ -73,7 +75,7 @@ impl CommandRequest for LoadRequest {
}
}
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(LoadRequest {
name: playlist_name,

View File

@@ -17,6 +17,8 @@ pub struct PlaylistAddRequest {
impl CommandRequest for PlaylistAddRequest {
const COMMAND: &'static str = "playlistadd";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::PlaylistAdd(self.playlist_name, self.uri, self.position)
@@ -53,12 +55,12 @@ impl CommandRequest for PlaylistAddRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let playlist_name = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(0))?
.to_string();
let uri = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(1))?
.to_string();
let position = parts
@@ -69,7 +71,7 @@ impl CommandRequest for PlaylistAddRequest {
})
.transpose()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(PlaylistAddRequest {
playlist_name,

View File

@@ -16,6 +16,8 @@ pub struct PlaylistDeleteRequest {
impl CommandRequest for PlaylistDeleteRequest {
const COMMAND: &'static str = "playlistdelete";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::PlaylistDelete(self.playlist_name, self.position)
@@ -45,7 +47,7 @@ impl CommandRequest for PlaylistDeleteRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let playlist_name = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(0))?
.to_string();
// TODO: this can be a range, according to docs
@@ -54,7 +56,7 @@ impl CommandRequest for PlaylistDeleteRequest {
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, position.to_string()))?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(PlaylistDeleteRequest {
playlist_name,

View File

@@ -17,6 +17,8 @@ pub struct PlaylistMoveRequest {
impl CommandRequest for PlaylistMoveRequest {
const COMMAND: &'static str = "playlistmove";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::PlaylistMove(self.playlist_name, self.from, self.to)
@@ -53,7 +55,7 @@ impl CommandRequest for PlaylistMoveRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let playlist_name = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(0))?
.to_string();
let mut from = None;
@@ -61,7 +63,7 @@ impl CommandRequest for PlaylistMoveRequest {
let to = parts.next();
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
let to = if let Some(to) = to {
from = Some(from_or_range_or_to.parse().map_err(|_| {

View File

@@ -15,6 +15,8 @@ pub struct RenameRequest {
impl CommandRequest for RenameRequest {
const COMMAND: &'static str = "rename";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(2);
fn into_request_enum(self) -> crate::Request {
crate::Request::Rename(self.old_name, self.new_name)
@@ -36,15 +38,15 @@ impl CommandRequest for RenameRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let old_name = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(0))?
.to_string();
let new_name = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(1))?
.to_string();
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(RenameRequest { old_name, new_name })
}

View File

@@ -16,6 +16,8 @@ pub struct SaveRequest {
impl CommandRequest for SaveRequest {
const COMMAND: &'static str = "save";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::Save(self.playlist_name, self.mode)
@@ -45,7 +47,7 @@ impl CommandRequest for SaveRequest {
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let playlist_name = parts
.next()
.ok_or(RequestParserError::UnexpectedEOF)?
.ok_or(Self::missing_arguments_error(0))?
.to_string();
let mode = parts
@@ -56,7 +58,7 @@ impl CommandRequest for SaveRequest {
})
.transpose()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SaveRequest {
playlist_name,

View File

@@ -18,6 +18,8 @@ pub struct SearchPlaylistRequest {
impl CommandRequest for SearchPlaylistRequest {
const COMMAND: &'static str = "searchplaylist";
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(3);
fn into_request_enum(self) -> crate::Request {
crate::Request::SearchPlaylist(self.name, self.filter, self.range)
@@ -44,7 +46,7 @@ impl CommandRequest for SearchPlaylistRequest {
}
fn parse(mut parts: RequestTokenizer<'_>) -> Result<Self, RequestParserError> {
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let name = parts.next().ok_or(Self::missing_arguments_error(0))?;
let name = name
.parse::<PlaylistName>()
.map_err(|_| RequestParserError::SyntaxError(0, name.to_owned()))?;
@@ -64,7 +66,7 @@ impl CommandRequest for SearchPlaylistRequest {
})
.transpose()?;
debug_assert!(parts.next().is_none());
Self::throw_if_too_many_arguments(parts)?;
Ok(SearchPlaylistRequest {
name,