Add more commands
This commit is contained in:
parent
3e512092bd
commit
2ee6bbc582
@ -4,17 +4,27 @@ use crate::Request;
|
|||||||
|
|
||||||
mod audio_output_devices;
|
mod audio_output_devices;
|
||||||
mod client_to_client;
|
mod client_to_client;
|
||||||
|
mod connection_settings;
|
||||||
mod controlling_playback;
|
mod controlling_playback;
|
||||||
|
mod mounts_and_neighbors;
|
||||||
|
mod partition_commands;
|
||||||
mod playback_options;
|
mod playback_options;
|
||||||
mod querying_mpd_status;
|
mod querying_mpd_status;
|
||||||
mod queue;
|
mod queue;
|
||||||
|
mod reflection;
|
||||||
|
mod stored_playlists;
|
||||||
|
|
||||||
pub use audio_output_devices::*;
|
pub use audio_output_devices::*;
|
||||||
pub use client_to_client::*;
|
pub use client_to_client::*;
|
||||||
|
pub use connection_settings::*;
|
||||||
pub use controlling_playback::*;
|
pub use controlling_playback::*;
|
||||||
|
pub use mounts_and_neighbors::*;
|
||||||
|
pub use partition_commands::*;
|
||||||
pub use playback_options::*;
|
pub use playback_options::*;
|
||||||
pub use querying_mpd_status::*;
|
pub use querying_mpd_status::*;
|
||||||
pub use queue::*;
|
pub use queue::*;
|
||||||
|
pub use reflection::*;
|
||||||
|
pub use stored_playlists::*;
|
||||||
|
|
||||||
pub trait Command {
|
pub trait Command {
|
||||||
type Response;
|
type Response;
|
||||||
@ -87,10 +97,13 @@ pub enum RequestParserError {
|
|||||||
MissingNewline,
|
MissingNewline,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: should these be renamed to fit the mpd docs?
|
||||||
|
// "Attribute" instead of "Property"?
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum ResponseParserError<'a> {
|
pub enum ResponseParserError<'a> {
|
||||||
MissingProperty(&'a str),
|
MissingProperty(&'a str),
|
||||||
UnexpectedPropertyType(&'a str, &'a str),
|
UnexpectedPropertyType(&'a str, &'a str),
|
||||||
|
UnexpectedProperty(&'a str),
|
||||||
InvalidProperty(&'a str, &'a str),
|
InvalidProperty(&'a str, &'a str),
|
||||||
SyntaxError(u64, &'a str),
|
SyntaxError(u64, &'a str),
|
||||||
UnexpectedEOF,
|
UnexpectedEOF,
|
||||||
|
@ -8,4 +8,4 @@ pub use disableoutput::DisableOutput;
|
|||||||
pub use enableoutput::EnableOutput;
|
pub use enableoutput::EnableOutput;
|
||||||
pub use outputs::Outputs;
|
pub use outputs::Outputs;
|
||||||
pub use outputset::OutputSet;
|
pub use outputset::OutputSet;
|
||||||
pub use toggleoutput::ToggleOutput;
|
pub use toggleoutput::ToggleOutput;
|
||||||
|
37
src/commands/connection_settings.rs
Normal file
37
src/commands/connection_settings.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
pub mod binary_limit;
|
||||||
|
pub mod close;
|
||||||
|
pub mod kill;
|
||||||
|
pub mod password;
|
||||||
|
pub mod ping;
|
||||||
|
pub mod protocol;
|
||||||
|
pub mod protocol_all;
|
||||||
|
pub mod protocol_available;
|
||||||
|
pub mod protocol_clear;
|
||||||
|
pub mod protocol_disable;
|
||||||
|
pub mod protocol_enable;
|
||||||
|
pub mod tag_types;
|
||||||
|
pub mod tag_types_all;
|
||||||
|
pub mod tag_types_available;
|
||||||
|
pub mod tag_types_clear;
|
||||||
|
pub mod tag_types_disable;
|
||||||
|
pub mod tag_types_enable;
|
||||||
|
pub mod tag_types_reset;
|
||||||
|
|
||||||
|
pub use binary_limit::BinaryLimit;
|
||||||
|
pub use close::Close;
|
||||||
|
pub use kill::Kill;
|
||||||
|
pub use password::Password;
|
||||||
|
pub use ping::Ping;
|
||||||
|
pub use protocol::Protocol;
|
||||||
|
pub use protocol_all::ProtocolAll;
|
||||||
|
pub use protocol_available::ProtocolAvailable;
|
||||||
|
pub use protocol_clear::ProtocolClear;
|
||||||
|
pub use protocol_disable::ProtocolDisable;
|
||||||
|
pub use protocol_enable::ProtocolEnable;
|
||||||
|
pub use tag_types::TagTypes;
|
||||||
|
pub use tag_types_all::TagTypesAll;
|
||||||
|
pub use tag_types_available::TagTypesAvailable;
|
||||||
|
pub use tag_types_clear::TagTypesClear;
|
||||||
|
pub use tag_types_disable::TagTypesDisable;
|
||||||
|
pub use tag_types_enable::TagTypesEnable;
|
||||||
|
pub use tag_types_reset::TagTypesReset;
|
27
src/commands/connection_settings/binary_limit.rs
Normal file
27
src/commands/connection_settings/binary_limit.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct BinaryLimit;
|
||||||
|
|
||||||
|
impl Command for BinaryLimit {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "binarylimit";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let limit = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let limit = limit
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, limit.to_string()))?;
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::BinaryLimit(limit), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
22
src/commands/connection_settings/close.rs
Normal file
22
src/commands/connection_settings/close.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Close;
|
||||||
|
|
||||||
|
impl Command for Close {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "close";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::Close, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
22
src/commands/connection_settings/kill.rs
Normal file
22
src/commands/connection_settings/kill.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Kill;
|
||||||
|
|
||||||
|
impl Command for Kill {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "kill";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::Kill, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
27
src/commands/connection_settings/password.rs
Normal file
27
src/commands/connection_settings/password.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Password;
|
||||||
|
|
||||||
|
impl Command for Password {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "password";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let password = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::Password(password), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
22
src/commands/connection_settings/ping.rs
Normal file
22
src/commands/connection_settings/ping.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Ping;
|
||||||
|
|
||||||
|
impl Command for Ping {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "ping";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::Ping, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
22
src/commands/connection_settings/protocol.rs
Normal file
22
src/commands/connection_settings/protocol.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{Command, RequestParserResult, ResponseAttributes, ResponseParserError},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Protocol;
|
||||||
|
|
||||||
|
impl Command for Protocol {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "protocol";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::Protocol, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
23
src/commands/connection_settings/protocol_all.rs
Normal file
23
src/commands/connection_settings/protocol_all.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{Command, RequestParserResult, ResponseAttributes, ResponseParserError},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ProtocolAll;
|
||||||
|
|
||||||
|
impl Command for ProtocolAll {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "protocol all";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::ProtocolAll, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
22
src/commands/connection_settings/protocol_available.rs
Normal file
22
src/commands/connection_settings/protocol_available.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{Command, RequestParserResult, ResponseAttributes, ResponseParserError},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ProtocolAvailable;
|
||||||
|
|
||||||
|
impl Command for ProtocolAvailable {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "protocol available";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::ProtocolAvailable, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
23
src/commands/connection_settings/protocol_clear.rs
Normal file
23
src/commands/connection_settings/protocol_clear.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{Command, RequestParserResult, ResponseAttributes, ResponseParserError},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ProtocolClear;
|
||||||
|
|
||||||
|
impl Command for ProtocolClear {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "protocol clear";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::ProtocolClear, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
34
src/commands/connection_settings/protocol_disable.rs
Normal file
34
src/commands/connection_settings/protocol_disable.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ProtocolDisable;
|
||||||
|
|
||||||
|
impl Command for ProtocolDisable {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "protocol disable";
|
||||||
|
|
||||||
|
fn parse_request(parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let mut parts = parts.peekable();
|
||||||
|
if parts.peek().is_none() {
|
||||||
|
return Err(RequestParserError::UnexpectedEOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut protocols = Vec::new();
|
||||||
|
for protocol in parts {
|
||||||
|
protocols.push(protocol.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((Request::ProtocolDisable(protocols), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
34
src/commands/connection_settings/protocol_enable.rs
Normal file
34
src/commands/connection_settings/protocol_enable.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ProtocolEnable;
|
||||||
|
|
||||||
|
impl Command for ProtocolEnable {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "protocol enable";
|
||||||
|
|
||||||
|
fn parse_request(parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let mut parts = parts.peekable();
|
||||||
|
if parts.peek().is_none() {
|
||||||
|
return Err(RequestParserError::UnexpectedEOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut protocols = Vec::new();
|
||||||
|
for protocol in parts {
|
||||||
|
protocols.push(protocol.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((Request::ProtocolEnable(protocols), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
42
src/commands/connection_settings/tag_types.rs
Normal file
42
src/commands/connection_settings/tag_types.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TagTypes;
|
||||||
|
|
||||||
|
pub type TagTypesResponse = Vec<String>;
|
||||||
|
|
||||||
|
impl Command for TagTypes {
|
||||||
|
type Response = TagTypesResponse;
|
||||||
|
const COMMAND: &'static str = "tagtypes";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::TagTypes, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: Vec<_> = parts.into();
|
||||||
|
|
||||||
|
let mut tagtypes = Vec::with_capacity(parts.len());
|
||||||
|
for (key, value) in parts.into_iter() {
|
||||||
|
debug_assert_eq!(key, "tagtype");
|
||||||
|
|
||||||
|
let tagtype = match value {
|
||||||
|
GenericResponseValue::Text(name) => name.to_string(),
|
||||||
|
GenericResponseValue::Binary(_) => {
|
||||||
|
return Err(ResponseParserError::UnexpectedPropertyType(
|
||||||
|
"tagtype", "Binary",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tagtypes.push(tagtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(tagtypes)
|
||||||
|
}
|
||||||
|
}
|
23
src/commands/connection_settings/tag_types_all.rs
Normal file
23
src/commands/connection_settings/tag_types_all.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{Command, RequestParserResult, ResponseAttributes, ResponseParserError},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TagTypesAll;
|
||||||
|
|
||||||
|
impl Command for TagTypesAll {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "tagtypes all";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::TagTypesAll, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
22
src/commands/connection_settings/tag_types_available.rs
Normal file
22
src/commands/connection_settings/tag_types_available.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{Command, RequestParserResult, ResponseAttributes, ResponseParserError},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TagTypesAvailable;
|
||||||
|
|
||||||
|
impl Command for TagTypesAvailable {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "tagtypes available";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::TagTypesAvailable, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
23
src/commands/connection_settings/tag_types_clear.rs
Normal file
23
src/commands/connection_settings/tag_types_clear.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{Command, RequestParserResult, ResponseAttributes, ResponseParserError},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TagTypesClear;
|
||||||
|
|
||||||
|
impl Command for TagTypesClear {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "tagtypes clear";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::TagTypesClear, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
34
src/commands/connection_settings/tag_types_disable.rs
Normal file
34
src/commands/connection_settings/tag_types_disable.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TagTypesDisable;
|
||||||
|
|
||||||
|
impl Command for TagTypesDisable {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "tagtypes disable";
|
||||||
|
|
||||||
|
fn parse_request(parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let mut parts = parts.peekable();
|
||||||
|
if parts.peek().is_none() {
|
||||||
|
return Err(RequestParserError::UnexpectedEOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tag_types = Vec::new();
|
||||||
|
for tag_type in parts {
|
||||||
|
tag_types.push(tag_type.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((Request::TagTypesDisable(tag_types), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
34
src/commands/connection_settings/tag_types_enable.rs
Normal file
34
src/commands/connection_settings/tag_types_enable.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TagTypesEnable;
|
||||||
|
|
||||||
|
impl Command for TagTypesEnable {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "tagtypes enable";
|
||||||
|
|
||||||
|
fn parse_request(parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let mut parts = parts.peekable();
|
||||||
|
if parts.peek().is_none() {
|
||||||
|
return Err(RequestParserError::UnexpectedEOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tag_types = Vec::new();
|
||||||
|
for tag_type in parts {
|
||||||
|
tag_types.push(tag_type.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((Request::TagTypesEnable(tag_types), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
34
src/commands/connection_settings/tag_types_reset.rs
Normal file
34
src/commands/connection_settings/tag_types_reset.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TagTypesReset;
|
||||||
|
|
||||||
|
impl Command for TagTypesReset {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "tagtypes reset";
|
||||||
|
|
||||||
|
fn parse_request(parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let mut parts = parts.peekable();
|
||||||
|
if parts.peek().is_none() {
|
||||||
|
return Err(RequestParserError::UnexpectedEOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tag_types = Vec::new();
|
||||||
|
for tag_type in parts {
|
||||||
|
tag_types.push(tag_type.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((Request::TagTypesReset(tag_types), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
9
src/commands/mounts_and_neighbors.rs
Normal file
9
src/commands/mounts_and_neighbors.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pub mod listmounts;
|
||||||
|
pub mod listneighbors;
|
||||||
|
pub mod mount;
|
||||||
|
pub mod unmount;
|
||||||
|
|
||||||
|
pub use listmounts::ListMounts;
|
||||||
|
pub use listneighbors::ListNeighbors;
|
||||||
|
pub use mount::Mount;
|
||||||
|
pub use unmount::Unmount;
|
49
src/commands/mounts_and_neighbors/listmounts.rs
Normal file
49
src/commands/mounts_and_neighbors/listmounts.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
// pub struct Unmount;
|
||||||
|
|
||||||
|
// impl Command for Unmount {
|
||||||
|
// type Response = ();
|
||||||
|
// const COMMAND: &'static str = "unmount";
|
||||||
|
|
||||||
|
// fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
// let path = parts
|
||||||
|
// .next()
|
||||||
|
// .ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
// .to_string();
|
||||||
|
|
||||||
|
// debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
// Ok((Request::Unmount(path), ""))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn parse_response(
|
||||||
|
// parts: ResponseAttributes<'_>,
|
||||||
|
// ) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
// debug_assert!(parts.is_empty());
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub struct ListMounts;
|
||||||
|
|
||||||
|
impl Command for ListMounts {
|
||||||
|
type Response = Vec<(String, String)>;
|
||||||
|
const COMMAND: &'static str = "listmounts";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::ListMounts, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
24
src/commands/mounts_and_neighbors/listneighbors.rs
Normal file
24
src/commands/mounts_and_neighbors/listneighbors.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ListNeighbors;
|
||||||
|
|
||||||
|
impl Command for ListNeighbors {
|
||||||
|
type Response = Vec<(String, String)>;
|
||||||
|
const COMMAND: &'static str = "listneighbors";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::ListNeighbors, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
36
src/commands/mounts_and_neighbors/mount.rs
Normal file
36
src/commands/mounts_and_neighbors/mount.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Mount;
|
||||||
|
|
||||||
|
impl Command for Mount {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "mount";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let path = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let uri = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::Mount(path, uri), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
31
src/commands/mounts_and_neighbors/unmount.rs
Normal file
31
src/commands/mounts_and_neighbors/unmount.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
Request,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Unmount;
|
||||||
|
|
||||||
|
impl Command for Unmount {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "unmount";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let path = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::Unmount(path), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
11
src/commands/partition_commands.rs
Normal file
11
src/commands/partition_commands.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
pub mod delpartition;
|
||||||
|
pub mod listpartitions;
|
||||||
|
pub mod moveoutput;
|
||||||
|
pub mod newpartition;
|
||||||
|
pub mod partition;
|
||||||
|
|
||||||
|
pub use delpartition::DelPartition;
|
||||||
|
pub use listpartitions::ListPartitions;
|
||||||
|
pub use moveoutput::MoveOutput;
|
||||||
|
pub use newpartition::NewPartition;
|
||||||
|
pub use partition::Partition;
|
29
src/commands/partition_commands/delpartition.rs
Normal file
29
src/commands/partition_commands/delpartition.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct DelPartition;
|
||||||
|
|
||||||
|
impl Command for DelPartition {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "delpartition";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let partition = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::DelPartition(partition), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
43
src/commands/partition_commands/listpartitions.rs
Normal file
43
src/commands/partition_commands/listpartitions.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ListPartitions;
|
||||||
|
|
||||||
|
pub type ListPartitionsResponse = Vec<String>;
|
||||||
|
|
||||||
|
impl Command for ListPartitions {
|
||||||
|
type Response = ListPartitionsResponse;
|
||||||
|
const COMMAND: &'static str = "listpartitions";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::ListPartitions, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: Vec<_> = parts.into();
|
||||||
|
|
||||||
|
let mut partitions = Vec::with_capacity(parts.len());
|
||||||
|
for (key, value) in parts.into_iter() {
|
||||||
|
debug_assert_eq!(key, "partition");
|
||||||
|
|
||||||
|
let partition = match value {
|
||||||
|
GenericResponseValue::Text(name) => name.to_string(),
|
||||||
|
GenericResponseValue::Binary(_) => {
|
||||||
|
return Err(ResponseParserError::UnexpectedPropertyType(
|
||||||
|
"partition",
|
||||||
|
"Binary",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
partitions.push(partition);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(partitions)
|
||||||
|
}
|
||||||
|
}
|
29
src/commands/partition_commands/moveoutput.rs
Normal file
29
src/commands/partition_commands/moveoutput.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct MoveOutput;
|
||||||
|
|
||||||
|
impl Command for MoveOutput {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "moveoutput";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let output_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::MoveOutput(output_name), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
29
src/commands/partition_commands/newpartition.rs
Normal file
29
src/commands/partition_commands/newpartition.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct NewPartition;
|
||||||
|
|
||||||
|
impl Command for NewPartition {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "newpartition";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let partition = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::NewPartition(partition), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
29
src/commands/partition_commands/partition.rs
Normal file
29
src/commands/partition_commands/partition.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Partition;
|
||||||
|
|
||||||
|
impl Command for Partition {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "partition";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let partition = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::Partition(partition), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,12 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::{commands::{
|
use crate::{
|
||||||
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
commands::{
|
||||||
ResponseParserError,
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
}, request::VolumeValue};
|
ResponseParserError,
|
||||||
|
},
|
||||||
|
request::VolumeValue,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Volume;
|
pub struct Volume;
|
||||||
|
|
||||||
|
11
src/commands/reflection.rs
Normal file
11
src/commands/reflection.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
pub mod commands;
|
||||||
|
pub mod config;
|
||||||
|
pub mod decoders;
|
||||||
|
pub mod not_commands;
|
||||||
|
pub mod url_handlers;
|
||||||
|
|
||||||
|
pub use commands::Commands;
|
||||||
|
pub use config::Config;
|
||||||
|
pub use decoders::Decoders;
|
||||||
|
pub use not_commands::NotCommands;
|
||||||
|
pub use url_handlers::UrlHandlers;
|
21
src/commands/reflection/commands.rs
Normal file
21
src/commands/reflection/commands.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Commands;
|
||||||
|
|
||||||
|
impl Command for Commands {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "commands";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::Commands, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
42
src/commands/reflection/config.rs
Normal file
42
src/commands/reflection/config.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::commands::{
|
||||||
|
get_and_parse_property, get_property, Command, Request, RequestParserResult,
|
||||||
|
ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Config;
|
||||||
|
|
||||||
|
pub struct ConfigResponse {
|
||||||
|
pub music_directory: String,
|
||||||
|
pub playlist_directory: String,
|
||||||
|
pub pcre: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Config {
|
||||||
|
type Response = ConfigResponse;
|
||||||
|
const COMMAND: &'static str = "config";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::Config, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: HashMap<_, _> = parts.into();
|
||||||
|
|
||||||
|
let music_directory = get_property!(parts, "music_directory", Text).to_string();
|
||||||
|
let playlist_directory = get_property!(parts, "playlist_directory", Text).to_string();
|
||||||
|
|
||||||
|
// TODO: is this parsed correctly?
|
||||||
|
let pcre = get_and_parse_property!(parts, "pcre", Text);
|
||||||
|
|
||||||
|
Ok(ConfigResponse {
|
||||||
|
music_directory,
|
||||||
|
playlist_directory,
|
||||||
|
pcre,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
29
src/commands/reflection/decoders.rs
Normal file
29
src/commands/reflection/decoders.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Decoders;
|
||||||
|
|
||||||
|
pub struct Decoder {
|
||||||
|
pub plugin: String,
|
||||||
|
pub suffixes: Vec<String>,
|
||||||
|
pub mime_types: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DecodersResponse = Vec<Decoder>;
|
||||||
|
|
||||||
|
impl Command for Decoders {
|
||||||
|
type Response = DecodersResponse;
|
||||||
|
const COMMAND: &'static str = "decoders";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::Decoders, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
21
src/commands/reflection/not_commands.rs
Normal file
21
src/commands/reflection/not_commands.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct NotCommands;
|
||||||
|
|
||||||
|
impl Command for NotCommands {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "not_commands";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::NotCommands, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
40
src/commands/reflection/url_handlers.rs
Normal file
40
src/commands/reflection/url_handlers.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct UrlHandlers;
|
||||||
|
|
||||||
|
pub type UrlHandlersResponse = Vec<String>;
|
||||||
|
|
||||||
|
impl Command for UrlHandlers {
|
||||||
|
type Response = UrlHandlersResponse;
|
||||||
|
const COMMAND: &'static str = "urlhandlers";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::UrlHandlers, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: Vec<_> = parts.into();
|
||||||
|
let mut url_handlers = Vec::new();
|
||||||
|
for (key, value) in parts.into_iter() {
|
||||||
|
if key != "handler" {
|
||||||
|
return Err(ResponseParserError::UnexpectedProperty(key));
|
||||||
|
}
|
||||||
|
let value = match value {
|
||||||
|
GenericResponseValue::Text(value) => value,
|
||||||
|
GenericResponseValue::Binary(_) => {
|
||||||
|
return Err(ResponseParserError::UnexpectedPropertyType(
|
||||||
|
"handler", "Binary",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
url_handlers.push(value.to_string());
|
||||||
|
}
|
||||||
|
Ok(url_handlers)
|
||||||
|
}
|
||||||
|
}
|
27
src/commands/stored_playlists.rs
Normal file
27
src/commands/stored_playlists.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
pub mod listplaylist;
|
||||||
|
pub mod listplaylistinfo;
|
||||||
|
pub mod listplaylists;
|
||||||
|
pub mod load;
|
||||||
|
pub mod playlistadd;
|
||||||
|
pub mod playlistclear;
|
||||||
|
pub mod playlistdelete;
|
||||||
|
pub mod playlistlength;
|
||||||
|
pub mod playlistmove;
|
||||||
|
pub mod rename;
|
||||||
|
pub mod rm;
|
||||||
|
pub mod save;
|
||||||
|
pub mod searchplaylist;
|
||||||
|
|
||||||
|
pub use listplaylist::ListPlaylist;
|
||||||
|
pub use listplaylistinfo::ListPlaylistInfo;
|
||||||
|
pub use listplaylists::ListPlaylists;
|
||||||
|
pub use load::Load;
|
||||||
|
pub use playlistadd::PlaylistAdd;
|
||||||
|
pub use playlistclear::PlaylistClear;
|
||||||
|
pub use playlistdelete::PlaylistDelete;
|
||||||
|
pub use playlistlength::PlaylistLength;
|
||||||
|
pub use playlistmove::PlaylistMove;
|
||||||
|
pub use rename::Rename;
|
||||||
|
pub use rm::Rm;
|
||||||
|
pub use save::Save;
|
||||||
|
pub use searchplaylist::SearchPlaylist;
|
53
src/commands/stored_playlists/listplaylist.rs
Normal file
53
src/commands/stored_playlists/listplaylist.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserError, RequestParserResult,
|
||||||
|
ResponseAttributes, ResponseParserError,
|
||||||
|
},
|
||||||
|
common::PlaylistName,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ListPlaylist;
|
||||||
|
|
||||||
|
pub type ListPlaylistResponse = Vec<PlaylistName>;
|
||||||
|
|
||||||
|
impl Command for ListPlaylist {
|
||||||
|
type Response = ListPlaylistResponse;
|
||||||
|
const COMMAND: &'static str = "listplaylist";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse::<PlaylistName>()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, name.to_owned()))?;
|
||||||
|
|
||||||
|
let range = parts
|
||||||
|
.next()
|
||||||
|
.map(|s| {
|
||||||
|
s.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, s.to_owned()))
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::ListPlaylist(name.to_string(), range), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: Vec<_> = parts.into();
|
||||||
|
parts
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, value)| {
|
||||||
|
debug_assert_eq!(name, "file");
|
||||||
|
match value {
|
||||||
|
GenericResponseValue::Text(value) => Ok(value.to_string()),
|
||||||
|
GenericResponseValue::Binary(_) => Err(
|
||||||
|
ResponseParserError::UnexpectedPropertyType("file", "Binary"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
}
|
||||||
|
}
|
39
src/commands/stored_playlists/listplaylistinfo.rs
Normal file
39
src/commands/stored_playlists/listplaylistinfo.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
},
|
||||||
|
common::PlaylistName,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ListPlaylistInfo;
|
||||||
|
|
||||||
|
impl Command for ListPlaylistInfo {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "listplaylistinfo";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse::<PlaylistName>()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, name.to_owned()))?;
|
||||||
|
|
||||||
|
let range = parts
|
||||||
|
.next()
|
||||||
|
.map(|s| {
|
||||||
|
s.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, s.to_owned()))
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::ListPlaylistInfo(name, range), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
21
src/commands/stored_playlists/listplaylists.rs
Normal file
21
src/commands/stored_playlists/listplaylists.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserResult, ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ListPlaylists;
|
||||||
|
|
||||||
|
impl Command for ListPlaylists {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "listplaylists";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
Ok((Request::ListPlaylists, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
46
src/commands/stored_playlists/load.rs
Normal file
46
src/commands/stored_playlists/load.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Load;
|
||||||
|
|
||||||
|
impl Command for Load {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "load";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let playlist_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let mut range = None;
|
||||||
|
let mut pos = None;
|
||||||
|
|
||||||
|
for _ in 0..2 {
|
||||||
|
if let Some(range_or_pos) = parts.next() {
|
||||||
|
if range_or_pos.contains(':') {
|
||||||
|
range = Some(range_or_pos.parse().map_err(|_| {
|
||||||
|
RequestParserError::SyntaxError(0, range_or_pos.to_owned())
|
||||||
|
})?);
|
||||||
|
} else {
|
||||||
|
pos = Some(range_or_pos.parse().map_err(|_| {
|
||||||
|
RequestParserError::SyntaxError(0, range_or_pos.to_owned())
|
||||||
|
})?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::Load(playlist_name, range, pos), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
42
src/commands/stored_playlists/playlistadd.rs
Normal file
42
src/commands/stored_playlists/playlistadd.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PlaylistAdd;
|
||||||
|
|
||||||
|
impl Command for PlaylistAdd {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "playlistadd";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let playlist_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let uri = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let position = parts
|
||||||
|
.next()
|
||||||
|
.map(|s| {
|
||||||
|
s.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, s.to_owned()))
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::PlaylistAdd(playlist_name, uri, position), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
29
src/commands/stored_playlists/playlistclear.rs
Normal file
29
src/commands/stored_playlists/playlistclear.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PlaylistClear;
|
||||||
|
|
||||||
|
impl Command for PlaylistClear {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "playlistclear";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let playlist_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::PlaylistClear(playlist_name), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
35
src/commands/stored_playlists/playlistdelete.rs
Normal file
35
src/commands/stored_playlists/playlistdelete.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PlaylistDelete;
|
||||||
|
|
||||||
|
impl Command for PlaylistDelete {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "playlistdelete";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let playlist_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
// TODO: this can be a range, according to docs
|
||||||
|
let position = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let position = position
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, position.to_string()))?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::PlaylistDelete(playlist_name, position), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
40
src/commands/stored_playlists/playlistlength.rs
Normal file
40
src/commands/stored_playlists/playlistlength.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::commands::{
|
||||||
|
get_and_parse_property, Command, Request, RequestParserError, RequestParserResult,
|
||||||
|
ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PlaylistLength;
|
||||||
|
|
||||||
|
pub struct PlaylistLengthResponse {
|
||||||
|
pub songs: u64,
|
||||||
|
pub playtime: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for PlaylistLength {
|
||||||
|
type Response = PlaylistLengthResponse;
|
||||||
|
const COMMAND: &'static str = "playlistlength";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let playlist_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::PlaylistLength(playlist_name), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: HashMap<_, _> = parts.into();
|
||||||
|
|
||||||
|
let songs = get_and_parse_property!(parts, "songs", Text);
|
||||||
|
let playtime = get_and_parse_property!(parts, "playtime", Text);
|
||||||
|
|
||||||
|
Ok(PlaylistLengthResponse { songs, playtime })
|
||||||
|
}
|
||||||
|
}
|
46
src/commands/stored_playlists/playlistmove.rs
Normal file
46
src/commands/stored_playlists/playlistmove.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PlaylistMove;
|
||||||
|
|
||||||
|
impl Command for PlaylistMove {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "playlistmove";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let playlist_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let mut from = None;
|
||||||
|
let from_or_range_or_to = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
|
||||||
|
let to = parts.next();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
let to = if let Some(to) = to {
|
||||||
|
from = Some(from_or_range_or_to.parse().map_err(|_| {
|
||||||
|
RequestParserError::SyntaxError(0, from_or_range_or_to.to_string())
|
||||||
|
})?);
|
||||||
|
to.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, to.to_string()))?
|
||||||
|
} else {
|
||||||
|
from_or_range_or_to
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, from_or_range_or_to.to_string()))?
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((Request::PlaylistMove(playlist_name, from, to), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
34
src/commands/stored_playlists/rename.rs
Normal file
34
src/commands/stored_playlists/rename.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Rename;
|
||||||
|
|
||||||
|
impl Command for Rename {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "rename";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let old_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let new_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::Rename(old_name, new_name), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
29
src/commands/stored_playlists/rm.rs
Normal file
29
src/commands/stored_playlists/rm.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Rm;
|
||||||
|
|
||||||
|
impl Command for Rm {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "rm";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let playlist_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::Rm(playlist_name), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
37
src/commands/stored_playlists/save.rs
Normal file
37
src/commands/stored_playlists/save.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Save;
|
||||||
|
|
||||||
|
impl Command for Save {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "save";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let playlist_name = parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let mode = parts
|
||||||
|
.next()
|
||||||
|
.map(|m| {
|
||||||
|
m.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, m.to_string()))
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::Save(playlist_name, mode), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
44
src/commands/stored_playlists/searchplaylist.rs
Normal file
44
src/commands/stored_playlists/searchplaylist.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
use crate::{
|
||||||
|
commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
},
|
||||||
|
common::{Filter, PlaylistName},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct SearchPlaylist;
|
||||||
|
|
||||||
|
impl Command for SearchPlaylist {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "searchplaylist";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse::<PlaylistName>()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, name.to_owned()))?;
|
||||||
|
|
||||||
|
let filter = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let filter = filter
|
||||||
|
.parse::<Filter>()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, filter.to_owned()))?;
|
||||||
|
|
||||||
|
let range = parts
|
||||||
|
.next()
|
||||||
|
.map(|s| {
|
||||||
|
s.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, s.to_owned()))
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::SearchPlaylist(name, filter, range), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
@ -80,13 +80,13 @@ pub enum Request {
|
|||||||
ListPlaylistInfo(PlaylistName, Option<WindowRange>),
|
ListPlaylistInfo(PlaylistName, Option<WindowRange>),
|
||||||
SearchPlaylist(PlaylistName, Filter, Option<WindowRange>),
|
SearchPlaylist(PlaylistName, Filter, Option<WindowRange>),
|
||||||
ListPlaylists,
|
ListPlaylists,
|
||||||
Load(PlaylistName, Option<WindowRange>, SongPosition),
|
Load(PlaylistName, Option<WindowRange>, Option<SongPosition>),
|
||||||
PlaylistAdd(PlaylistName, Uri, SongPosition),
|
PlaylistAdd(PlaylistName, Uri, Option<SongPosition>),
|
||||||
PlaylistClear(PlaylistName),
|
PlaylistClear(PlaylistName),
|
||||||
PlaylistDelete(PlaylistName, OneOrRange),
|
PlaylistDelete(PlaylistName, OneOrRange),
|
||||||
PlaylistLength(PlaylistName),
|
PlaylistLength(PlaylistName),
|
||||||
// TODO: which type of range?
|
// TODO: which type of range?
|
||||||
PlaylistMove(PlaylistName, OneOrRange, SongPosition),
|
PlaylistMove(PlaylistName, Option<OneOrRange>, SongPosition),
|
||||||
Rename(PlaylistName, PlaylistName),
|
Rename(PlaylistName, PlaylistName),
|
||||||
Rm(PlaylistName),
|
Rm(PlaylistName),
|
||||||
Save(PlaylistName, Option<SaveMode>),
|
Save(PlaylistName, Option<SaveMode>),
|
||||||
@ -129,7 +129,7 @@ pub enum Request {
|
|||||||
Rescan(Option<Uri>),
|
Rescan(Option<Uri>),
|
||||||
|
|
||||||
// -- Mount and Neighbor Commands -- //
|
// -- Mount and Neighbor Commands -- //
|
||||||
Mount(Option<Path>, Option<Uri>),
|
Mount(Path, Uri),
|
||||||
Unmount(Path),
|
Unmount(Path),
|
||||||
ListMounts,
|
ListMounts,
|
||||||
ListNeighbors,
|
ListNeighbors,
|
||||||
@ -159,12 +159,12 @@ pub enum Request {
|
|||||||
Ping,
|
Ping,
|
||||||
BinaryLimit(u64),
|
BinaryLimit(u64),
|
||||||
TagTypes,
|
TagTypes,
|
||||||
TagTypesDisable(Vec<Tag>),
|
TagTypesDisable(Vec<TagName>),
|
||||||
TagTypesEnable(Vec<Tag>),
|
TagTypesEnable(Vec<TagName>),
|
||||||
TagTypesClear,
|
TagTypesClear,
|
||||||
TagTypesAll,
|
TagTypesAll,
|
||||||
TagTypesAvailable,
|
TagTypesAvailable,
|
||||||
TagTypesReset(Vec<Tag>),
|
TagTypesReset(Vec<TagName>),
|
||||||
Protocol,
|
Protocol,
|
||||||
ProtocolDisable(Vec<Feature>),
|
ProtocolDisable(Vec<Feature>),
|
||||||
ProtocolEnable(Vec<Feature>),
|
ProtocolEnable(Vec<Feature>),
|
||||||
@ -410,16 +410,56 @@ impl Request {
|
|||||||
ClearTagId::COMMAND => ClearTagId::parse_request(parts),
|
ClearTagId::COMMAND => ClearTagId::parse_request(parts),
|
||||||
|
|
||||||
/* stored playlists */
|
/* stored playlists */
|
||||||
|
ListPlaylist::COMMAND => ListPlaylist::parse_request(parts),
|
||||||
|
ListPlaylistInfo::COMMAND => ListPlaylistInfo::parse_request(parts),
|
||||||
|
SearchPlaylist::COMMAND => SearchPlaylist::parse_request(parts),
|
||||||
|
ListPlaylists::COMMAND => ListPlaylists::parse_request(parts),
|
||||||
|
Load::COMMAND => Load::parse_request(parts),
|
||||||
|
PlaylistAdd::COMMAND => PlaylistAdd::parse_request(parts),
|
||||||
|
PlaylistClear::COMMAND => PlaylistClear::parse_request(parts),
|
||||||
|
PlaylistDelete::COMMAND => PlaylistDelete::parse_request(parts),
|
||||||
|
PlaylistLength::COMMAND => PlaylistLength::parse_request(parts),
|
||||||
|
PlaylistMove::COMMAND => PlaylistMove::parse_request(parts),
|
||||||
|
Rename::COMMAND => Rename::parse_request(parts),
|
||||||
|
Rm::COMMAND => Rm::parse_request(parts),
|
||||||
|
Save::COMMAND => Save::parse_request(parts),
|
||||||
|
|
||||||
/* music database */
|
/* music database */
|
||||||
|
|
||||||
/* mounts and neighbors */
|
/* mounts and neighbors */
|
||||||
|
Mount::COMMAND => Mount::parse_request(parts),
|
||||||
|
Unmount::COMMAND => Unmount::parse_request(parts),
|
||||||
|
ListMounts::COMMAND => ListMounts::parse_request(parts),
|
||||||
|
ListNeighbors::COMMAND => ListNeighbors::parse_request(parts),
|
||||||
|
|
||||||
/* stickers */
|
/* stickers */
|
||||||
|
|
||||||
/* connection settings */
|
/* connection settings */
|
||||||
|
Close::COMMAND => Close::parse_request(parts),
|
||||||
|
Kill::COMMAND => Kill::parse_request(parts),
|
||||||
|
Password::COMMAND => Password::parse_request(parts),
|
||||||
|
Ping::COMMAND => Ping::parse_request(parts),
|
||||||
|
BinaryLimit::COMMAND => BinaryLimit::parse_request(parts),
|
||||||
|
TagTypes::COMMAND => TagTypes::parse_request(parts),
|
||||||
|
TagTypesDisable::COMMAND => TagTypesDisable::parse_request(parts),
|
||||||
|
TagTypesEnable::COMMAND => TagTypesEnable::parse_request(parts),
|
||||||
|
TagTypesClear::COMMAND => TagTypesClear::parse_request(parts),
|
||||||
|
TagTypesAll::COMMAND => TagTypesAll::parse_request(parts),
|
||||||
|
TagTypesAvailable::COMMAND => TagTypesAvailable::parse_request(parts),
|
||||||
|
TagTypesReset::COMMAND => TagTypesReset::parse_request(parts),
|
||||||
|
Protocol::COMMAND => Protocol::parse_request(parts),
|
||||||
|
ProtocolDisable::COMMAND => ProtocolDisable::parse_request(parts),
|
||||||
|
ProtocolEnable::COMMAND => ProtocolEnable::parse_request(parts),
|
||||||
|
ProtocolClear::COMMAND => ProtocolClear::parse_request(parts),
|
||||||
|
ProtocolAll::COMMAND => ProtocolAll::parse_request(parts),
|
||||||
|
ProtocolAvailable::COMMAND => ProtocolAvailable::parse_request(parts),
|
||||||
|
|
||||||
/* partition commands */
|
/* partition commands */
|
||||||
|
Partition::COMMAND => Partition::parse_request(parts),
|
||||||
|
ListPartitions::COMMAND => ListPartitions::parse_request(parts),
|
||||||
|
NewPartition::COMMAND => NewPartition::parse_request(parts),
|
||||||
|
DelPartition::COMMAND => DelPartition::parse_request(parts),
|
||||||
|
MoveOutput::COMMAND => MoveOutput::parse_request(parts),
|
||||||
|
|
||||||
/* audio output devices */
|
/* audio output devices */
|
||||||
DisableOutput::COMMAND => DisableOutput::parse_request(parts),
|
DisableOutput::COMMAND => DisableOutput::parse_request(parts),
|
||||||
@ -429,6 +469,11 @@ impl Request {
|
|||||||
OutputSet::COMMAND => OutputSet::parse_request(parts),
|
OutputSet::COMMAND => OutputSet::parse_request(parts),
|
||||||
|
|
||||||
/* reflection */
|
/* reflection */
|
||||||
|
Config::COMMAND => Config::parse_request(parts),
|
||||||
|
Commands::COMMAND => Commands::parse_request(parts),
|
||||||
|
NotCommands::COMMAND => NotCommands::parse_request(parts),
|
||||||
|
UrlHandlers::COMMAND => UrlHandlers::parse_request(parts),
|
||||||
|
Decoders::COMMAND => Decoders::parse_request(parts),
|
||||||
|
|
||||||
/* client to client */
|
/* client to client */
|
||||||
Subscribe::COMMAND => Subscribe::parse_request(parts),
|
Subscribe::COMMAND => Subscribe::parse_request(parts),
|
||||||
|
Loading…
Reference in New Issue
Block a user