commands: remove toplevel Request/Response enums

This also exposes all the command types as public API
This commit is contained in:
2026-06-21 14:41:28 +09:00
parent e701aeab17
commit 56d7c942db
86 changed files with 22 additions and 2094 deletions
+16 -8
View File
@@ -4,7 +4,7 @@
//! managing the playlist, and returns the expected response types directly
//! from its methods.
use crate::{Request, commands::*, types::SongPosition};
use crate::{commands::*, types::SongPosition};
#[cfg(feature = "futures")]
use futures_util::{
@@ -106,12 +106,11 @@ where
Ok(response)
}
pub async fn play(
&mut self,
position: Option<SongPosition>,
) -> Result<PlayResponse, MpdClientError> {
let message = Request::Play(position);
let payload = message.serialize();
pub async fn execute<C>(&mut self, request: C::Request) -> Result<C::Response, MpdClientError>
where
C: Command,
{
let payload = request.serialize();
self.stream
.write_all(payload.as_bytes())
@@ -124,7 +123,16 @@ where
.map_err(MpdClientError::ConnectionError)?;
let response_bytes = self.read_response().await?;
let response = PlayResponse::parse_raw(&response_bytes)?;
let response = C::Response::parse_raw(&response_bytes)?;
Ok(response)
}
pub async fn play(
&mut self,
position: Option<SongPosition>,
) -> Result<PlayResponse, MpdClientError> {
let request = <Play as Command>::Request::new(position);
self.execute::<Play>(request).await
}
}
+5 -160
View File
@@ -9,6 +9,9 @@
use crate::{request_tokenizer::RequestTokenizer, response_tokenizer::ResponseAttributes};
use serde::{Deserialize, Serialize};
use thiserror::Error;
mod audio_output_devices;
mod client_to_client;
mod connection_settings;
@@ -34,22 +37,11 @@ pub use playback_options::*;
pub use querying_mpd_status::*;
pub use queue::*;
pub use reflection::*;
use serde::{Deserialize, Serialize};
pub use stickers::*;
pub use stored_playlists::*;
#[cfg(feature = "futures")]
use futures_util::{
AsyncBufReadExt,
io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufReader},
};
use thiserror::Error;
#[cfg(feature = "tokio")]
use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader};
/// A trait modelling a single MPD command request.
pub(crate) trait CommandRequest
pub trait CommandRequest
where
Self: Sized,
{
@@ -96,14 +88,6 @@ where
}
}
/// Converts this specific request type to it's corresponding variant in the generic Request enum.
fn into_request_enum(self) -> crate::Request;
/// Converts from the generic Request enum to this specific request type.
///
/// If the enum variant does not match this type, returns None.
fn from_request_enum(request: crate::Request) -> Option<Self>;
/// Serializes the request into a String.
fn serialize(&self) -> String;
@@ -145,18 +129,10 @@ where
}
/// A trait modelling a single MPD command response.
pub(crate) trait CommandResponse
pub trait CommandResponse
where
Self: Sized,
{
/// Converts this specific response type to it's corresponding variant in the generic Response enum.
fn into_response_enum(self) -> crate::Response;
/// Converts from the generic Response enum to this specific response type.
///
/// If the enum variant does not match this type, returns None.
fn from_response_enum(response: crate::Response) -> Option<Self>;
// /// Serializes the response into a Vec<u8>.
// fn serialize(&self) -> Vec<u8>;
@@ -180,16 +156,6 @@ pub trait Command {
/// The command name used within the protocol
const COMMAND: &'static str = Self::Request::COMMAND;
/// Serialize the request into a string.
/// This should optimally produce an input that can be parsed by [`parse_request`]
fn serialize_request(&self, request: Self::Request) -> String {
request.serialize().to_owned()
}
/// Serialize the request into a bytestring.
fn serialize_request_to_bytes(&self, request: Self::Request) -> Vec<u8> {
self.serialize_request(request).into_bytes()
}
/// Parse the request from its tokenized parts. See also [`parse_raw_request`].
fn parse_request(parts: RequestTokenizer) -> Result<Self::Request, RequestParserError> {
Self::Request::parse(parts)
@@ -212,55 +178,6 @@ pub trait Command {
fn parse_raw_response(raw: &[u8]) -> Result<Self::Response, ResponseParserError> {
Self::Response::parse_raw(raw)
}
async fn execute<T>(
request: Self::Request,
connection: &mut T,
) -> Result<Self::Response, crate::MpdClientError>
where
Self: Sized,
T: AsyncWrite + AsyncRead + Unpin,
{
let payload = request.serialize();
connection
.write_all(payload.as_bytes())
.await
.map_err(crate::MpdClientError::ConnectionError)?;
connection
.flush()
.await
.map_err(crate::MpdClientError::ConnectionError)?;
let mut response_bytes = Vec::new();
let mut reader = BufReader::new(connection);
loop {
let mut line = Vec::new();
let bytes_read = reader
.read_until(b'\n', &mut line)
.await
.map_err(crate::MpdClientError::ConnectionError)?;
if bytes_read == 0 {
break; // EOF reached
}
response_bytes.extend_from_slice(&line);
// TODO: handle errors properly
if line == b"OK\n" || line.starts_with(b"ACK ") {
break; // End of response
}
}
let response = Self::parse_raw_response(&response_bytes)
.map_err(crate::MpdClientError::ResponseParseError)?;
Ok(response)
}
}
// Request/response implementation helpers
@@ -277,22 +194,6 @@ macro_rules! empty_command_request {
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = Some(0);
fn into_request_enum(self) -> crate::Request {
match Self::COMMAND {
$command_name => crate::Request::$name,
_ => unimplemented!(),
}
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match (Self::COMMAND, request) {
($command_name, crate::Request::$name) => {
Some(paste::paste! { [<$name Request>] })
}
_ => None,
}
}
fn serialize(&self) -> String {
Self::COMMAND.to_string() + "\n"
}
@@ -316,14 +217,6 @@ macro_rules! empty_command_response {
}
impl crate::commands::CommandResponse for paste::paste! { [<$name Response>] } {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(
_parts: crate::commands::ResponseAttributes<'_>,
) -> Result<Self, crate::commands::ResponseParserError> {
@@ -346,22 +239,6 @@ macro_rules! single_item_command_request {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
match Self::COMMAND {
$command_name => crate::Request::$name(self.0),
_ => unimplemented!(),
}
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match (Self::COMMAND, request) {
($command_name, crate::Request::$name(item)) => {
Some(paste::paste! { [<$name Request>] ( item ) })
}
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {}\n", Self::COMMAND, self.0)
}
@@ -399,22 +276,6 @@ macro_rules! single_optional_item_command_request {
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
match Self::COMMAND {
$command_name => crate::Request::$name(self.0),
_ => unimplemented!(),
}
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match (Self::COMMAND, request) {
($command_name, crate::Request::$name(item)) => {
Some(paste::paste! { [<$name Request>] ( item ) })
}
_ => None,
}
}
fn serialize(&self) -> String {
match &self.0 {
Some(item) => format!("{} {}\n", Self::COMMAND, item),
@@ -454,14 +315,6 @@ macro_rules! single_item_command_response {
}
impl crate::commands::CommandResponse for paste::paste! { [<$name Response>] } {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(
parts: crate::commands::ResponseAttributes<'_>,
) -> Result<Self, crate::commands::ResponseParserError> {
@@ -498,14 +351,6 @@ macro_rules! multi_item_command_response {
}
impl crate::commands::CommandResponse for paste::paste! { [<$name Response>] } {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(
parts: crate::commands::ResponseAttributes<'_>,
) -> Result<Self, crate::commands::ResponseParserError> {
@@ -49,14 +49,6 @@ impl Output {
}
impl CommandResponse for OutputsResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts = parts.into_vec()?;
@@ -30,23 +30,6 @@ impl CommandRequest for OutputSetRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::OutputSet(output_id, attribute_name, attribute_value) => {
Some(OutputSetRequest {
output_id,
attribute_name,
attribute_value,
})
}
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {} {} {}",
@@ -22,14 +22,6 @@ impl ChannelsResponse {
}
impl CommandResponse for ChannelsResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: Vec<_> = parts.into_vec()?;
let mut channel_names = Vec::with_capacity(parts.len());
@@ -32,14 +32,6 @@ impl ReadMessagesResponseEntry {
}
impl CommandResponse for ReadMessagesResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: Vec<_> = parts.into_vec()?;
debug_assert!(parts.len() % 2 == 0);
@@ -25,19 +25,6 @@ impl CommandRequest for SendMessageRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::SendMessage(channel, message) => {
Some(SendMessageRequest { channel, message })
}
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}", Self::COMMAND, self.channel, self.message)
}
@@ -19,17 +19,6 @@ impl CommandRequest for ProtocolDisableRequest {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::ProtocolDisable(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::ProtocolDisable(features) => Some(ProtocolDisableRequest(features)),
_ => None,
}
}
fn serialize(&self) -> String {
let features = self
.0
@@ -19,17 +19,6 @@ impl CommandRequest for ProtocolEnableRequest {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::ProtocolEnable(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::ProtocolEnable(features) => Some(ProtocolEnableRequest(features)),
_ => None,
}
}
fn serialize(&self) -> String {
let features = self
.0
@@ -19,17 +19,6 @@ impl CommandRequest for TagTypesDisableRequest {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::TagTypesDisable(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::TagTypesDisable(req) => Some(TagTypesDisableRequest(req)),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {}",
@@ -19,17 +19,6 @@ impl CommandRequest for TagTypesEnableRequest {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::TagTypesEnable(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::TagTypesEnable(req) => Some(TagTypesEnableRequest(req)),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {}",
@@ -19,17 +19,6 @@ impl CommandRequest for TagTypesResetRequest {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::TagTypesReset(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::TagTypesReset(req) => Some(TagTypesResetRequest(req)),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {}",
@@ -18,17 +18,6 @@ impl CommandRequest for PauseRequest {
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::Pause(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Pause(value) => Some(PauseRequest(value)),
_ => None,
}
}
fn serialize(&self) -> String {
match self.0 {
Some(true) => format!("{} 1\n", Self::COMMAND),
-11
View File
@@ -25,17 +25,6 @@ impl CommandRequest for SeekRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Seek(songpos, time) => Some(SeekRequest { songpos, time }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.songpos, self.time)
}
@@ -25,17 +25,6 @@ impl CommandRequest for SeekCurRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::SeekCur(mode, time) => Some(SeekCurRequest { mode, time }),
_ => None,
}
}
fn serialize(&self) -> String {
let time_str = match self.mode {
SeekMode::Absolute => format!("{}", self.time),
@@ -25,17 +25,6 @@ impl CommandRequest for SeekIdRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::SeekId(songid, time) => Some(SeekIdRequest { songid, time }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.songid, self.time)
}
@@ -21,14 +21,6 @@ impl ListNeighborsResponse {
}
impl CommandResponse for ListNeighborsResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: Vec<_> = parts.into_vec()?;
debug_assert!(parts.len() % 2 == 0);
@@ -25,17 +25,6 @@ impl CommandRequest for MountRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Mount(path, uri) => Some(MountRequest { path, uri }),
_ => None,
}
}
fn serialize(&self) -> String {
debug_assert!(self.path.to_str().is_some());
format!(
@@ -21,17 +21,6 @@ impl CommandRequest for UnmountRequest {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::Unmount(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Unmount(item) => Some(UnmountRequest(item)),
_ => None,
}
}
fn serialize(&self) -> String {
debug_assert!(self.0.to_str().is_some());
format!(
-19
View File
@@ -28,17 +28,6 @@ impl CommandRequest for AlbumArtRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::AlbumArt(uri, offset) => Some(AlbumArtRequest { uri, offset }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.uri, self.offset)
}
@@ -82,14 +71,6 @@ impl AlbumArtResponse {
}
impl CommandResponse for AlbumArtResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
-19
View File
@@ -29,17 +29,6 @@ impl CommandRequest for CountRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Count(filter, group) => Some(CountRequest { filter, group }),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
if let Some(group) = self.group.as_ref() {
@@ -97,14 +86,6 @@ impl CountResponse {
}
impl CommandResponse for CountResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
-23
View File
@@ -32,21 +32,6 @@ impl CommandRequest for FindRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Find(filter, sort, window) => Some(FindRequest {
filter,
sort,
window,
}),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
if let Some(sort) = &self.sort {
@@ -128,14 +113,6 @@ impl FindResponse {
}
impl CommandResponse for FindResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
DbSelectionPrintResponse::parse(parts)?
.into_iter()
-16
View File
@@ -38,22 +38,6 @@ impl CommandRequest for FindAddRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::FindAdd(filter, sort, window, position) => Some(FindAddRequest {
filter,
sort,
window,
position,
}),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
if let Some(sort) = &self.sort {
@@ -24,14 +24,6 @@ impl GetFingerprintResponse {
}
impl CommandResponse for GetFingerprintResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
-24
View File
@@ -39,22 +39,6 @@ impl CommandRequest for ListRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::List(tagname, filter, groups, window) => Some(ListRequest {
tagname,
filter,
groups,
window,
}),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = match &self.filter {
Some(f) => format!("{} {} {}", Self::COMMAND, self.tagname, f),
@@ -161,14 +145,6 @@ impl ListResponse {
}
impl CommandResponse for ListResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts_: Vec<_> = parts.into_vec()?;
debug_assert!({
-8
View File
@@ -23,14 +23,6 @@ impl ListAllResponse {
}
impl CommandResponse for ListAllResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let result = DbSelectionPrintResponse::parse(parts)?;
@@ -23,14 +23,6 @@ impl ListAllInfoResponse {
}
impl CommandResponse for ListAllInfoResponse {
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let result = DbSelectionPrintResponse::parse(parts)?;
-8
View File
@@ -22,14 +22,6 @@ impl ListFilesResponse {
}
impl CommandResponse for ListFilesResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
DbSelectionPrintResponse::parse(parts)?
.into_iter()
-8
View File
@@ -22,14 +22,6 @@ impl LsInfoResponse {
}
impl CommandResponse for LsInfoResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let result = DbSelectionPrintResponse::parse(parts)?;
@@ -22,14 +22,6 @@ impl ReadCommentsResponse {
}
impl CommandResponse for ReadCommentsResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
@@ -30,17 +30,6 @@ impl CommandRequest for ReadPictureRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::ReadPicture(uri, offset) => Some(ReadPictureRequest { uri, offset }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.uri, self.offset)
}
@@ -89,14 +78,6 @@ impl ReadPictureResponse {
}
impl CommandResponse for ReadPictureResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
-8
View File
@@ -26,14 +26,6 @@ impl RescanResponse {
}
impl CommandResponse for RescanResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
-23
View File
@@ -32,21 +32,6 @@ impl CommandRequest for SearchRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Search(filter, sort, window) => Some(SearchRequest {
filter,
sort,
window,
}),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
if let Some(sort) = &self.sort {
@@ -128,14 +113,6 @@ impl SearchResponse {
}
impl CommandResponse for SearchResponse {
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
DbSelectionPrintResponse::parse(parts)?
.into_iter()
-16
View File
@@ -38,22 +38,6 @@ impl CommandRequest for SearchAddRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::SearchAdd(filter, sort, window, position) => Some(SearchAddRequest {
filter,
sort,
window,
position,
}),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
if let Some(sort) = &self.sort {
@@ -41,31 +41,6 @@ impl CommandRequest for SearchAddPlRequest {
const MIN_ARGS: u32 = 2;
const MAX_ARGS: Option<u32> = Some(5);
fn into_request_enum(self) -> crate::Request {
crate::Request::SearchAddPl(
self.playlist_name,
self.filter,
self.sort,
self.window,
self.position,
)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::SearchAddPl(playlist_name, filter, sort, window, position) => {
Some(SearchAddPlRequest {
playlist_name,
filter,
sort,
window,
position,
})
}
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {} {}", Self::COMMAND, self.playlist_name, self.filter);
if let Some(sort) = &self.sort {
@@ -29,19 +29,6 @@ impl CommandRequest for SearchCountRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::SearchCount(filter, group) => {
Some(SearchCountRequest { filter, group })
}
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
if let Some(group) = &self.group {
@@ -98,14 +85,6 @@ impl SearchCountResponse {
}
impl CommandResponse for SearchCountResponse {
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
-8
View File
@@ -26,14 +26,6 @@ impl UpdateResponse {
}
impl CommandResponse for UpdateResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
-11
View File
@@ -18,17 +18,6 @@ impl CommandRequest for RandomRequest {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::Random(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Random(state) => Some(RandomRequest(state)),
_ => None,
}
}
fn serialize(&self) -> String {
let state = if self.0 { "1" } else { "0" };
format!("{} {}\n", Self::COMMAND, state)
-11
View File
@@ -18,17 +18,6 @@ impl CommandRequest for RepeatRequest {
const MIN_ARGS: u32 = 1;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::Repeat(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Repeat(state) => Some(RepeatRequest(state)),
_ => None,
}
}
fn serialize(&self) -> String {
let state = if self.0 { "1" } else { "0" };
format!("{} {}\n", Self::COMMAND, state)
@@ -24,14 +24,6 @@ impl ReplayGainStatusResponse {
}
impl CommandResponse for ReplayGainStatusResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
let replay_gain_mode = get_property!(parts, "replay_gain_mode", Text);
@@ -40,14 +40,6 @@ impl CurrentSongResponse {
}
impl CommandResponse for CurrentSongResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let mut parts: HashMap<_, _> = parts.into_map()?;
-11
View File
@@ -21,17 +21,6 @@ impl CommandRequest for IdleRequest {
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = None;
fn into_request_enum(self) -> crate::Request {
crate::Request::Idle(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Idle(subsystems) => Some(IdleRequest(subsystems)),
_ => None,
}
}
fn serialize(&self) -> String {
match &self.0 {
Some(subsystems) => {
@@ -47,14 +47,6 @@ impl StatsResponse {
}
impl CommandResponse for StatsResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
@@ -122,14 +122,6 @@ impl StatusResponse {
}
impl CommandResponse for StatusResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
let partition = get_property!(parts, "partition", Text).to_string();
-11
View File
@@ -25,17 +25,6 @@ impl CommandRequest for AddRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Add(uri, position) => Some(AddRequest { uri, position }),
_ => None,
}
}
fn serialize(&self) -> String {
match self.position {
Some(position) => format!("{} {} {}\n", Self::COMMAND, self.uri, position),
-19
View File
@@ -26,17 +26,6 @@ impl CommandRequest for AddIdRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::AddId(uri, position) => Some(AddIdRequest { uri, position }),
_ => None,
}
}
fn serialize(&self) -> String {
match self.position {
Some(pos) => format!("{} {} {}\n", Self::COMMAND, self.uri, pos),
@@ -82,14 +71,6 @@ impl AddIdResponse {
}
impl CommandResponse for AddIdResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: Vec<_> = parts.into();
let mut iter = parts.into_iter();
-15
View File
@@ -30,21 +30,6 @@ impl CommandRequest for AddTagIdRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::AddTagId(songid, tag_name, tag_value) => Some(AddTagIdRequest {
songid,
tag_name,
tag_value,
}),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {} {} {}\n",
-13
View File
@@ -25,19 +25,6 @@ impl CommandRequest for ClearTagIdRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::ClearTagId(songid, tag_name) => {
Some(ClearTagIdRequest { songid, tag_name })
}
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.songid, self.tag_name)
}
-11
View File
@@ -25,17 +25,6 @@ impl CommandRequest for MoveRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Move(from_or_range, to) => Some(MoveRequest { from_or_range, to }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.from_or_range, self.to)
}
-11
View File
@@ -25,17 +25,6 @@ impl CommandRequest for MoveIdRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::MoveId(id, to) => Some(MoveIdRequest { id, to }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.id, self.to)
}
-8
View File
@@ -20,14 +20,6 @@ impl PlaylistResponse {
}
impl CommandResponse for PlaylistResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
unimplemented!()
}
-24
View File
@@ -1,7 +1,6 @@
use serde::{Deserialize, Serialize};
use crate::{
Response,
commands::{Command, CommandRequest, CommandResponse, RequestParserError, ResponseParserError},
filter::Filter,
request_tokenizer::RequestTokenizer,
@@ -33,21 +32,6 @@ impl CommandRequest for PlaylistFindRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::PlaylistFind(filter, sort, window) => Some(PlaylistFindRequest {
filter,
sort,
window,
}),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
if let Some(sort) = &self.sort {
@@ -153,14 +137,6 @@ impl PlaylistFindResponseEntry {
}
impl CommandResponse for PlaylistFindResponse {
fn into_response_enum(self) -> Response {
todo!()
}
fn from_response_enum(_response: Response) -> Option<Self> {
todo!()
}
fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
unimplemented!()
}
-8
View File
@@ -44,14 +44,6 @@ impl PlaylistIdResponseEntry {
}
impl CommandResponse for PlaylistIdResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
unimplemented!()
}
-8
View File
@@ -46,14 +46,6 @@ impl PlaylistInfoResponseEntry {
}
impl CommandResponse for PlaylistInfoResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
unimplemented!()
}
-23
View File
@@ -32,21 +32,6 @@ impl CommandRequest for PlaylistSearchRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::PlaylistSearch(filter, sort, window) => Some(PlaylistSearchRequest {
filter,
sort,
window,
}),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, self.filter);
if let Some(sort) = &self.sort {
@@ -152,14 +137,6 @@ impl PlaylistSearchResponseEntry {
}
impl CommandResponse for PlaylistSearchResponse {
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
unimplemented!()
}
-21
View File
@@ -26,19 +26,6 @@ impl CommandRequest for PlChangesRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::PlChanges(version, window) => {
Some(PlChangesRequest { version, window })
}
_ => None,
}
}
fn serialize(&self) -> String {
match self.window.as_ref() {
Some(window) => format!("{} {} {}\n", Self::COMMAND, self.version, window),
@@ -108,14 +95,6 @@ impl PlChangesResponseEntry {
}
impl CommandResponse for PlChangesResponse {
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
unimplemented!()
}
-21
View File
@@ -26,19 +26,6 @@ impl CommandRequest for PlChangesPosIdRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::PlChangesPosId(version, window) => {
Some(PlChangesPosIdRequest { version, window })
}
_ => None,
}
}
fn serialize(&self) -> String {
match self.window.as_ref() {
Some(window) => format!("{} {} {}\n", Self::COMMAND, self.version, window),
@@ -97,14 +84,6 @@ impl PlChangesPosIdResponseEntry {
}
impl CommandResponse for PlChangesPosIdResponse {
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
unimplemented!()
}
-11
View File
@@ -25,17 +25,6 @@ impl CommandRequest for PrioRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Prio(prio, window) => Some(PrioRequest { prio, window }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.prio, self.window)
}
-11
View File
@@ -26,17 +26,6 @@ impl CommandRequest for PrioIdRequest {
// 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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::PrioId(prio, songids) => Some(PrioIdRequest { prio, songids }),
_ => None,
}
}
fn serialize(&self) -> String {
let songids = self
.songids
-14
View File
@@ -28,20 +28,6 @@ impl CommandRequest for RangeIdRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::RangeId(songid, time_interval) => Some(RangeIdRequest {
songid,
time_interval,
}),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.songid, self.time_interval)
}
-11
View File
@@ -25,17 +25,6 @@ impl CommandRequest for SwapRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Swap(songpos1, songpos2) => Some(SwapRequest { songpos1, songpos2 }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.songpos1, self.songpos2)
}
-11
View File
@@ -25,17 +25,6 @@ impl CommandRequest for SwapIdRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::SwapId(songid1, songid2) => Some(SwapIdRequest { songid1, songid2 }),
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.songid1, self.songid2)
}
-8
View File
@@ -29,14 +29,6 @@ impl ConfigResponse {
}
impl CommandResponse for ConfigResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
-8
View File
@@ -36,14 +36,6 @@ impl DecodersResponse {
}
impl CommandResponse for DecodersResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let mut result = Vec::new();
let mut current_decoder: Option<Decoder> = None;
-16
View File
@@ -32,22 +32,6 @@ impl CommandRequest for StickerDecRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::StickerDec(sticker_type, uri, name, value) => Some(StickerDecRequest {
sticker_type,
uri,
name,
value,
}),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {} {} {} {}\n",
-15
View File
@@ -30,21 +30,6 @@ impl CommandRequest for StickerDeleteRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::StickerDelete(sticker_type, uri, name) => Some(StickerDeleteRequest {
sticker_type,
uri,
name,
}),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {} {} {}\n",
-33
View File
@@ -41,31 +41,6 @@ impl CommandRequest for StickerFindRequest {
const MIN_ARGS: u32 = 3;
const MAX_ARGS: Option<u32> = Some(5);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerFind(
self.sticker_type,
self.uri,
self.name,
self.sort,
self.window,
)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::StickerFind(sticker_type, uri, name, sort, window) => {
Some(StickerFindRequest {
sticker_type,
uri,
name,
sort,
window,
})
}
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!(
"{} {} {} {}",
@@ -189,14 +164,6 @@ impl StickerFindResponseEntry {
}
impl CommandResponse for StickerFindResponse {
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: Vec<_> = parts.into_vec()?;
let mut stickers = Vec::with_capacity(parts.len() / 2);
-15
View File
@@ -30,21 +30,6 @@ impl CommandRequest for StickerGetRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::StickerGet(sticker_type, uri, name) => Some(StickerGetRequest {
sticker_type,
uri,
name,
}),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {} {} {}\n",
-16
View File
@@ -32,22 +32,6 @@ impl CommandRequest for StickerIncRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::StickerInc(sticker_type, uri, name, value) => Some(StickerIncRequest {
sticker_type,
uri,
name,
value,
}),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {} {} {} {}\n",
-21
View File
@@ -28,19 +28,6 @@ impl CommandRequest for StickerListRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::StickerList(sticker_type, uri) => {
Some(StickerListRequest { sticker_type, uri })
}
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.sticker_type, self.uri)
}
@@ -81,14 +68,6 @@ impl StickerListResponse {
}
impl CommandResponse for StickerListResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: Vec<_> = parts.into_vec()?;
if let Some((k, _)) = parts.iter().find(|(k, _)| *k != "sticker") {
-16
View File
@@ -32,22 +32,6 @@ impl CommandRequest for StickerSetRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::StickerSet(sticker_type, uri, name, value) => Some(StickerSetRequest {
sticker_type,
uri,
name,
value,
}),
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {} {} {} {}\n",
@@ -25,19 +25,6 @@ impl CommandRequest for StickerNamesTypesRequest {
const MIN_ARGS: u32 = 0;
const MAX_ARGS: Option<u32> = Some(1);
fn into_request_enum(self) -> crate::Request {
crate::Request::StickerNamesTypes(self.0)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::StickerNamesTypes(sticker_type) => {
Some(StickerNamesTypesRequest(sticker_type))
}
_ => None,
}
}
fn serialize(&self) -> String {
if let Some(sticker_type) = &self.0 {
format!("{} {}\n", Self::COMMAND, sticker_type)
@@ -72,14 +59,6 @@ impl StickerNamesTypesResponse {
}
impl CommandResponse for StickerNamesTypesResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: Vec<_> = parts.into_vec()?;
debug_assert!(parts.len() % 2 == 0);
@@ -31,17 +31,6 @@ impl CommandRequest for ListPlaylistRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::ListPlaylist(name, range) => Some(ListPlaylistRequest { name, range }),
_ => None,
}
}
fn serialize(&self) -> String {
if let Some(range) = &self.range {
format!("{} {} {}\n", Self::COMMAND, self.name, range)
@@ -26,19 +26,6 @@ impl CommandRequest for ListPlaylistInfoRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::ListPlaylistInfo(name, range) => {
Some(ListPlaylistInfoRequest { name, range })
}
_ => None,
}
}
fn serialize(&self) -> String {
match self.range.as_ref() {
Some(range) => format!("{} {} {}\n", Self::COMMAND, self.name, range),
@@ -76,14 +63,6 @@ impl ListPlaylistInfoResponse {
}
impl CommandResponse for ListPlaylistInfoResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(_parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
unimplemented!()
}
@@ -36,14 +36,6 @@ impl ListPlaylistsResponseEntry {
}
impl CommandResponse for ListPlaylistsResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let mut parts = parts.into_lazy_vec().into_iter().peekable();
// TODO: count instances of 'playlist' to preallocate
-15
View File
@@ -34,21 +34,6 @@ impl CommandRequest for LoadRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Load(name, range, position) => Some(LoadRequest {
name,
range,
position,
}),
_ => None,
}
}
fn serialize(&self) -> String {
match (self.range.as_ref(), self.position.as_ref()) {
(Some(range), Some(pos)) => {
@@ -30,21 +30,6 @@ impl CommandRequest for PlaylistAddRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::PlaylistAdd(playlist_name, uri, position) => Some(PlaylistAddRequest {
playlist_name,
uri,
position,
}),
_ => None,
}
}
fn serialize(&self) -> String {
match self.position {
Some(pos) => {
@@ -28,22 +28,6 @@ impl CommandRequest for PlaylistDeleteRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::PlaylistDelete(playlist_name, position) => {
Some(PlaylistDeleteRequest {
playlist_name,
position,
})
}
_ => None,
}
}
fn serialize(&self) -> String {
format!(
"{} {} {}\n",
@@ -25,14 +25,6 @@ impl PlaylistLengthResponse {
}
impl CommandResponse for PlaylistLengthResponse {
fn into_response_enum(self) -> crate::Response {
todo!()
}
fn from_response_enum(_response: crate::Response) -> Option<Self> {
todo!()
}
fn parse(parts: ResponseAttributes<'_>) -> Result<Self, ResponseParserError> {
let parts: HashMap<_, _> = parts.into_map()?;
@@ -30,21 +30,6 @@ impl CommandRequest for PlaylistMoveRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::PlaylistMove(playlist_name, from, to) => Some(PlaylistMoveRequest {
playlist_name,
from,
to,
}),
_ => None,
}
}
fn serialize(&self) -> String {
match self.from.as_ref() {
Some(from) => {
-13
View File
@@ -24,19 +24,6 @@ impl CommandRequest for RenameRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Rename(old_name, new_name) => {
Some(RenameRequest { old_name, new_name })
}
_ => None,
}
}
fn serialize(&self) -> String {
format!("{} {} {}\n", Self::COMMAND, self.old_name, self.new_name)
}
-14
View File
@@ -28,20 +28,6 @@ impl CommandRequest for SaveRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::Save(playlist_name, mode) => Some(SaveRequest {
playlist_name,
mode,
}),
_ => None,
}
}
fn serialize(&self) -> String {
match self.mode.as_ref() {
Some(mode) => {
@@ -31,21 +31,6 @@ impl CommandRequest for SearchPlaylistRequest {
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)
}
fn from_request_enum(request: crate::Request) -> Option<Self> {
match request {
crate::Request::SearchPlaylist(name, filter, range) => Some(SearchPlaylistRequest {
name,
filter,
range,
}),
_ => None,
}
}
fn serialize(&self) -> String {
let mut cmd = format!("{} {} {}", Self::COMMAND, self.name, self.filter);
if let Some(range) = &self.range {
+1 -5
View File
@@ -4,17 +4,13 @@
//! It does not provide any client or server implementation
mod client;
mod commands;
mod request;
mod request_tokenizer;
mod response;
mod response_tokenizer;
mod server;
pub mod commands;
pub mod filter;
pub mod types;
pub use client::{MpdClient, MpdClientError};
pub use request::Request;
pub use response::Response;
pub use server::MpdServer;
-587
View File
@@ -1,587 +0,0 @@
use serde::{Deserialize, Serialize};
use crate::commands::*;
use crate::types::*;
use crate::filter::Filter;
use crate::request_tokenizer::RequestTokenizer;
// TODO: SingleLineString
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Request {
CommandList(Vec<Request>),
// -- Query Commands -- //
ClearError,
CurrentSong,
Idle(Option<Vec<SubSystem>>),
Status,
Stats,
// -- Playback Commands -- //
Consume(BoolOrOneshot),
Crossfade(Seconds),
MixRampDb(f32),
MixRampDelay(Seconds),
Random(bool),
Repeat(bool),
SetVol(VolumeValue),
GetVol,
Single(BoolOrOneshot),
ReplayGainMode(ReplayGainModeMode),
ReplayGainStatus,
Volume(VolumeValue),
// -- Playback Control Commands -- //
Next,
Pause(Option<bool>),
Play(Option<SongPosition>),
PlayId(Option<SongId>),
Previous,
Seek(SongPosition, TimeWithFractions),
SeekId(SongId, TimeWithFractions),
SeekCur(SeekMode, TimeWithFractions),
Stop,
// -- Queue Commands -- //
// TODO: relative mode
Add(String, Option<SongPosition>),
// TODO: relative mode
AddId(String, Option<SongPosition>),
Clear,
Delete(OneOrRange),
DeleteId(SongId),
// TODO: account for relative moves
Move(OneOrRange, AbsouluteRelativeSongPosition),
// TODO: account for relative moves
MoveId(SongId, AbsouluteRelativeSongPosition),
Playlist,
PlaylistFind(Filter, Option<Sort>, Option<WindowRange>),
PlaylistId(SongId),
PlaylistInfo(Option<OneOrRange>),
PlaylistSearch(Filter, Option<Sort>, Option<WindowRange>),
// TODO: which type of range?
PlChanges(PlaylistVersion, Option<WindowRange>),
// TODO: which type of range?
PlChangesPosId(PlaylistVersion, Option<WindowRange>),
// TODO: which type of range?
Prio(Priority, WindowRange),
PrioId(Priority, Vec<SongId>),
RangeId(SongId, TimeInterval),
Shuffle(Option<OneOrRange>),
Swap(SongPosition, SongPosition),
SwapId(SongId, SongId),
AddTagId(SongId, TagName, TagValue),
ClearTagId(SongId, TagName),
// -- Stored Playlist Commands -- //
ListPlaylist(PlaylistName, Option<WindowRange>),
ListPlaylistInfo(PlaylistName, Option<WindowRange>),
SearchPlaylist(PlaylistName, Filter, Option<WindowRange>),
ListPlaylists,
Load(PlaylistName, Option<WindowRange>, Option<SongPosition>),
PlaylistAdd(PlaylistName, Uri, Option<SongPosition>),
PlaylistClear(PlaylistName),
PlaylistDelete(PlaylistName, OneOrRange),
PlaylistLength(PlaylistName),
// TODO: which type of range?
PlaylistMove(PlaylistName, Option<OneOrRange>, SongPosition),
Rename(PlaylistName, PlaylistName),
Rm(PlaylistName),
Save(PlaylistName, Option<SaveMode>),
// -- Music Database Commands -- //
AlbumArt(Uri, Offset),
Count(Filter, Option<GroupType>),
GetFingerprint(Uri),
Find(Filter, Option<Sort>, Option<WindowRange>),
FindAdd(
Filter,
Option<Sort>,
Option<WindowRange>,
Option<SongPosition>,
),
List(TagName, Option<Filter>, Vec<GroupType>, Option<WindowRange>),
#[deprecated]
ListAll(Option<Uri>),
#[deprecated]
ListAllInfo(Option<Uri>),
ListFiles(Option<Uri>),
LsInfo(Option<Uri>),
ReadComments(Uri),
ReadPicture(Uri, Offset),
Search(Filter, Option<Sort>, Option<WindowRange>),
SearchAdd(
Filter,
Option<Sort>,
Option<WindowRange>,
Option<SongPosition>,
),
SearchAddPl(
PlaylistName,
Filter,
Option<Sort>,
Option<WindowRange>,
Option<SongPosition>,
),
SearchCount(Filter, Option<GroupType>),
Update(Option<Uri>),
Rescan(Option<Uri>),
// -- Mount and Neighbor Commands -- //
Mount(MountPath, Uri),
Unmount(MountPath),
ListMounts,
ListNeighbors,
// -- Sticker Commands -- //
StickerGet(StickerType, Uri, String),
StickerSet(StickerType, Uri, String, String),
StickerInc(StickerType, Uri, String, usize),
StickerDec(StickerType, Uri, String, usize),
StickerDelete(StickerType, Uri, String),
StickerList(StickerType, Uri),
StickerFind(StickerType, Uri, String, Option<Sort>, Option<WindowRange>),
StickerFindValue(
StickerType,
Uri,
String,
String,
Option<Sort>,
Option<WindowRange>,
),
StickerNames,
StickerTypes,
StickerNamesTypes(Option<StickerType>),
// -- Connection Commands -- //
Close,
Kill,
Password(String),
Ping,
BinaryLimit(u64),
TagTypes,
TagTypesDisable(Vec<TagName>),
TagTypesEnable(Vec<TagName>),
TagTypesClear,
TagTypesAll,
TagTypesAvailable,
TagTypesReset(Vec<TagName>),
Protocol,
ProtocolDisable(Vec<Feature>),
ProtocolEnable(Vec<Feature>),
ProtocolClear,
ProtocolAll,
ProtocolAvailable,
// -- Partition Commands -- //
Partition(PartitionName),
ListPartitions,
NewPartition(PartitionName),
DelPartition(PartitionName),
MoveOutput(String),
// -- Audio Output Commands -- //
DisableOutput(AudioOutputId),
EnableOutput(AudioOutputId),
ToggleOutput(AudioOutputId),
Outputs,
OutputSet(AudioOutputId, String, String),
// -- Reflection Commands -- //
Config,
Commands,
NotCommands,
UrlHandlers,
Decoders,
// -- Client to Client Commands -- //
Subscribe(ChannelName),
Unsubscribe(ChannelName),
Channels,
ReadMessages,
SendMessage(ChannelName, String),
}
macro_rules! serialize_req {
($request_enum:expr, $request_struct:ty) => {
{
if let Some(request) = <$request_struct as CommandRequest>::from_request_enum($request_enum) {
return <$request_struct as CommandRequest>::serialize(&request);
} else {
panic!("Mismatched request enum and struct in serialize_request macro, this should never happen!");
}
}
};
}
macro_rules! parse_req {
($request_struct:ty, $parts:expr) => {
<$request_struct>::parse($parts).map(|req| req.into_request_enum())
};
}
impl Request {
pub fn serialize(self) -> String {
match self {
/* querying mpd status */
Request::ClearError => serialize_req!(self, ClearErrorRequest),
Request::CurrentSong => serialize_req!(self, CurrentSongRequest),
Request::Idle(_) => serialize_req!(self, IdleRequest),
Request::Status => serialize_req!(self, StatusRequest),
Request::Stats => serialize_req!(self, StatsRequest),
// /* playback options */
Request::Consume(_) => serialize_req!(self, ConsumeRequest),
Request::Crossfade(_) => serialize_req!(self, CrossfadeRequest),
Request::MixRampDb(_) => serialize_req!(self, MixRampDbRequest),
Request::MixRampDelay(_) => serialize_req!(self, MixRampDelayRequest),
Request::Random(_) => serialize_req!(self, RandomRequest),
Request::Repeat(_) => serialize_req!(self, RepeatRequest),
Request::SetVol(_) => serialize_req!(self, SetVolRequest),
Request::GetVol => serialize_req!(self, GetVolRequest),
Request::Single(_) => serialize_req!(self, SingleRequest),
Request::ReplayGainMode(_) => serialize_req!(self, ReplayGainModeRequest),
Request::ReplayGainStatus => serialize_req!(self, ReplayGainStatusRequest),
Request::Volume(_) => serialize_req!(self, VolumeRequest),
/* playback control */
Request::Next => serialize_req!(self, NextRequest),
Request::Pause(_) => serialize_req!(self, PauseRequest),
Request::Play(_) => serialize_req!(self, PlayRequest),
Request::PlayId(_) => serialize_req!(self, PlayIdRequest),
Request::Previous => serialize_req!(self, PreviousRequest),
Request::Seek(_, _) => serialize_req!(self, SeekRequest),
Request::SeekId(_, _) => serialize_req!(self, SeekIdRequest),
Request::SeekCur(_, _) => serialize_req!(self, SeekCurRequest),
Request::Stop => serialize_req!(self, StopRequest),
/* queue */
Request::Add(_, _) => serialize_req!(self, AddRequest),
Request::AddId(_, _) => serialize_req!(self, AddIdRequest),
Request::Clear => serialize_req!(self, ClearRequest),
Request::Delete(_) => serialize_req!(self, DeleteRequest),
Request::DeleteId(_) => serialize_req!(self, DeleteIdRequest),
Request::Move(_, _) => serialize_req!(self, MoveRequest),
Request::MoveId(_, _) => serialize_req!(self, MoveIdRequest),
Request::Playlist => serialize_req!(self, PlaylistRequest),
Request::PlaylistFind(_, _, _) => serialize_req!(self, PlaylistFindRequest),
Request::PlaylistId(_) => serialize_req!(self, PlaylistIdRequest),
Request::PlaylistInfo(_) => serialize_req!(self, PlaylistInfoRequest),
Request::PlaylistSearch(_, _, _) => serialize_req!(self, PlaylistSearchRequest),
Request::PlChanges(_, _) => serialize_req!(self, PlChangesRequest),
Request::PlChangesPosId(_, _) => serialize_req!(self, PlChangesPosIdRequest),
Request::Prio(_, _) => serialize_req!(self, PrioRequest),
Request::PrioId(_, _) => serialize_req!(self, PrioIdRequest),
Request::RangeId(_, _) => serialize_req!(self, RangeIdRequest),
Request::Shuffle(_) => serialize_req!(self, ShuffleRequest),
Request::Swap(_, _) => serialize_req!(self, SwapRequest),
Request::SwapId(_, _) => serialize_req!(self, SwapIdRequest),
Request::AddTagId(_, _, _) => serialize_req!(self, AddTagIdRequest),
Request::ClearTagId(_, _) => serialize_req!(self, ClearTagIdRequest),
/* stored playlists */
Request::ListPlaylist(_, _) => serialize_req!(self, ListPlaylistRequest),
Request::ListPlaylistInfo(_, _) => serialize_req!(self, ListPlaylistInfoRequest),
Request::SearchPlaylist(_, _, _) => serialize_req!(self, SearchPlaylistRequest),
Request::ListPlaylists => serialize_req!(self, ListPlaylistsRequest),
Request::Load(_, _, _) => serialize_req!(self, LoadRequest),
Request::PlaylistAdd(_, _, _) => serialize_req!(self, PlaylistAddRequest),
Request::PlaylistClear(_) => serialize_req!(self, PlaylistClearRequest),
Request::PlaylistDelete(_, _) => serialize_req!(self, PlaylistDeleteRequest),
Request::PlaylistLength(_) => serialize_req!(self, PlaylistLengthRequest),
Request::PlaylistMove(_, _, _) => serialize_req!(self, PlaylistMoveRequest),
Request::Rename(_, _) => serialize_req!(self, RenameRequest),
Request::Rm(_) => serialize_req!(self, RmRequest),
Request::Save(_, _) => serialize_req!(self, SaveRequest),
/* music database */
Request::AlbumArt(_, _) => serialize_req!(self, AlbumArtRequest),
Request::Count(_, _) => serialize_req!(self, CountRequest),
Request::GetFingerprint(_) => serialize_req!(self, GetFingerprintRequest),
Request::Find(_, _, _) => serialize_req!(self, FindRequest),
Request::FindAdd(_, _, _, _) => serialize_req!(self, FindAddRequest),
Request::List(_, _, _, _) => serialize_req!(self, ListRequest),
Request::ListAll(_) => serialize_req!(self, ListAllRequest),
Request::ListAllInfo(_) => serialize_req!(self, ListAllInfoRequest),
Request::ListFiles(_) => serialize_req!(self, ListFilesRequest),
Request::LsInfo(_) => serialize_req!(self, LsInfoRequest),
Request::ReadComments(_) => serialize_req!(self, ReadCommentsRequest),
Request::ReadPicture(_, _) => serialize_req!(self, ReadPictureRequest),
Request::Search(_, _, _) => serialize_req!(self, SearchRequest),
Request::SearchAdd(_, _, _, _) => serialize_req!(self, SearchAddRequest),
Request::SearchAddPl(_, _, _, _, _) => serialize_req!(self, SearchAddPlRequest),
Request::SearchCount(_, _) => serialize_req!(self, SearchCountRequest),
Request::Update(_) => serialize_req!(self, UpdateRequest),
Request::Rescan(_) => serialize_req!(self, RescanRequest),
/* mounts and neighbors */
Request::Mount(_, _) => serialize_req!(self, MountRequest),
Request::Unmount(_) => serialize_req!(self, UnmountRequest),
Request::ListMounts => serialize_req!(self, ListMountsRequest),
Request::ListNeighbors => serialize_req!(self, ListNeighborsRequest),
/* stickers */
Request::StickerGet(_, _, _) => serialize_req!(self, StickerGetRequest),
Request::StickerSet(_, _, _, _) => serialize_req!(self, StickerSetRequest),
Request::StickerInc(_, _, _, _) => serialize_req!(self, StickerIncRequest),
Request::StickerDec(_, _, _, _) => serialize_req!(self, StickerDecRequest),
Request::StickerDelete(_, _, _) => serialize_req!(self, StickerDeleteRequest),
Request::StickerList(_, _) => serialize_req!(self, StickerListRequest),
Request::StickerFind(_, _, _, _, _) => serialize_req!(self, StickerFindRequest),
Request::StickerNames => serialize_req!(self, StickerNamesRequest),
Request::StickerTypes => serialize_req!(self, StickerTypesRequest),
Request::StickerNamesTypes(_) => serialize_req!(self, StickerNamesTypesRequest),
/* connection settings */
Request::Close => serialize_req!(self, CloseRequest),
Request::Kill => serialize_req!(self, KillRequest),
Request::Password(_) => serialize_req!(self, PasswordRequest),
Request::Ping => serialize_req!(self, PingRequest),
Request::BinaryLimit(_) => serialize_req!(self, BinaryLimitRequest),
Request::TagTypes => serialize_req!(self, TagTypesRequest),
Request::TagTypesDisable(_) => serialize_req!(self, TagTypesDisableRequest),
Request::TagTypesEnable(_) => serialize_req!(self, TagTypesEnableRequest),
Request::TagTypesClear => serialize_req!(self, TagTypesClearRequest),
Request::TagTypesAll => serialize_req!(self, TagTypesAllRequest),
Request::TagTypesAvailable => serialize_req!(self, TagTypesAvailableRequest),
Request::TagTypesReset(_) => serialize_req!(self, TagTypesResetRequest),
Request::Protocol => serialize_req!(self, ProtocolRequest),
Request::ProtocolDisable(_) => serialize_req!(self, ProtocolDisableRequest),
Request::ProtocolEnable(_) => serialize_req!(self, ProtocolEnableRequest),
Request::ProtocolClear => serialize_req!(self, ProtocolClearRequest),
Request::ProtocolAll => serialize_req!(self, ProtocolAllRequest),
Request::ProtocolAvailable => serialize_req!(self, ProtocolAvailableRequest),
/* partition commands */
Request::Partition(_) => serialize_req!(self, PartitionRequest),
Request::ListPartitions => serialize_req!(self, ListPartitionsRequest),
Request::NewPartition(_) => serialize_req!(self, NewPartitionRequest),
Request::DelPartition(_) => serialize_req!(self, DelPartitionRequest),
Request::MoveOutput(_) => serialize_req!(self, MoveOutputRequest),
/* audio output devices */
Request::DisableOutput(_) => serialize_req!(self, DisableOutputRequest),
Request::EnableOutput(_) => serialize_req!(self, EnableOutputRequest),
Request::ToggleOutput(_) => serialize_req!(self, ToggleOutputRequest),
Request::Outputs => serialize_req!(self, OutputsRequest),
Request::OutputSet(_, _, _) => serialize_req!(self, OutputSetRequest),
/* reflection */
Request::Config => serialize_req!(self, ConfigRequest),
Request::Commands => serialize_req!(self, CommandsRequest),
Request::NotCommands => serialize_req!(self, NotCommandsRequest),
Request::UrlHandlers => serialize_req!(self, UrlHandlersRequest),
Request::Decoders => serialize_req!(self, DecodersRequest),
/* client to client */
Request::Subscribe(_) => serialize_req!(self, SubscribeRequest),
Request::Unsubscribe(_) => serialize_req!(self, UnsubscribeRequest),
Request::Channels => serialize_req!(self, ChannelsRequest),
Request::ReadMessages => serialize_req!(self, ReadMessagesRequest),
Request::SendMessage(_, _) => serialize_req!(self, SendMessageRequest),
_ => unimplemented!(),
}
}
// TODO: upon encountering an error, there should be a function that lets you skip to the next OK,
// and continue execution. Maybe "parse_next_or_skip(&str) -> RequestParserResponse", which
// could skip stuff internally? Or do we want to report back the error with the entire command
// and let the library user decide what to do?
//
// TODO: should this return the remaining &str as well?
pub fn parse_next(raw: &str) -> Result<Self, RequestParserError> {
let (line, rest) = raw
.split_once('\n')
.ok_or(RequestParserError::UnexpectedEOF)?;
let mut parts = RequestTokenizer::new(line);
match parts.next().ok_or(RequestParserError::EmptyLine)?.trim() {
"command_list_begin" => {
let mut commands = Vec::new();
let mut i = 1;
loop {
i += 1;
let (line, _rest) = rest
.split_once('\n')
.ok_or(RequestParserError::MissingCommandListEnd)?;
match line.trim() {
"command_list_begin" => {
return Err(RequestParserError::NestedCommandList { line: i });
}
"command_list_end" => {
return Ok(Request::CommandList(commands));
}
input => {
let command = Request::parse_next(input)?;
commands.push(command);
}
}
}
}
"command_list_end" => Err(RequestParserError::UnexpectedCommandListEnd),
/* querying mpd status */
ClearErrorRequest::COMMAND => parse_req!(ClearErrorRequest, parts),
CurrentSongRequest::COMMAND => parse_req!(CurrentSongRequest, parts),
IdleRequest::COMMAND => parse_req!(IdleRequest, parts),
StatusRequest::COMMAND => parse_req!(StatusRequest, parts),
StatsRequest::COMMAND => parse_req!(StatsRequest, parts),
/* playback options */
ConsumeRequest::COMMAND => parse_req!(ConsumeRequest, parts),
CrossfadeRequest::COMMAND => parse_req!(CrossfadeRequest, parts),
MixRampDbRequest::COMMAND => parse_req!(MixRampDbRequest, parts),
MixRampDelayRequest::COMMAND => parse_req!(MixRampDelayRequest, parts),
RandomRequest::COMMAND => parse_req!(RandomRequest, parts),
RepeatRequest::COMMAND => parse_req!(RepeatRequest, parts),
SetVolRequest::COMMAND => parse_req!(SetVolRequest, parts),
GetVolRequest::COMMAND => parse_req!(GetVolRequest, parts),
SingleRequest::COMMAND => parse_req!(SingleRequest, parts),
ReplayGainModeRequest::COMMAND => parse_req!(ReplayGainModeRequest, parts),
ReplayGainStatusRequest::COMMAND => parse_req!(ReplayGainStatusRequest, parts),
VolumeRequest::COMMAND => parse_req!(VolumeRequest, parts),
/* playback control */
NextRequest::COMMAND => parse_req!(NextRequest, parts),
PauseRequest::COMMAND => parse_req!(PauseRequest, parts),
PlayRequest::COMMAND => parse_req!(PlayRequest, parts),
PlayIdRequest::COMMAND => parse_req!(PlayIdRequest, parts),
PreviousRequest::COMMAND => parse_req!(PreviousRequest, parts),
SeekRequest::COMMAND => parse_req!(SeekRequest, parts),
SeekIdRequest::COMMAND => parse_req!(SeekIdRequest, parts),
SeekCurRequest::COMMAND => parse_req!(SeekCurRequest, parts),
StopRequest::COMMAND => parse_req!(StopRequest, parts),
/* queue */
AddRequest::COMMAND => parse_req!(AddRequest, parts),
AddIdRequest::COMMAND => parse_req!(AddIdRequest, parts),
ClearRequest::COMMAND => parse_req!(ClearRequest, parts),
DeleteRequest::COMMAND => parse_req!(DeleteRequest, parts),
DeleteIdRequest::COMMAND => parse_req!(DeleteIdRequest, parts),
MoveRequest::COMMAND => parse_req!(MoveRequest, parts),
MoveIdRequest::COMMAND => parse_req!(MoveIdRequest, parts),
PlaylistRequest::COMMAND => parse_req!(PlaylistRequest, parts),
PlaylistFindRequest::COMMAND => parse_req!(PlaylistFindRequest, parts),
PlaylistIdRequest::COMMAND => parse_req!(PlaylistIdRequest, parts),
PlaylistInfoRequest::COMMAND => parse_req!(PlaylistInfoRequest, parts),
PlaylistSearchRequest::COMMAND => parse_req!(PlaylistSearchRequest, parts),
PlChangesRequest::COMMAND => parse_req!(PlChangesRequest, parts),
PlChangesPosIdRequest::COMMAND => parse_req!(PlChangesPosIdRequest, parts),
PrioRequest::COMMAND => parse_req!(PrioRequest, parts),
PrioIdRequest::COMMAND => parse_req!(PrioIdRequest, parts),
RangeIdRequest::COMMAND => parse_req!(RangeIdRequest, parts),
ShuffleRequest::COMMAND => parse_req!(ShuffleRequest, parts),
SwapRequest::COMMAND => parse_req!(SwapRequest, parts),
SwapIdRequest::COMMAND => parse_req!(SwapIdRequest, parts),
AddTagIdRequest::COMMAND => parse_req!(AddTagIdRequest, parts),
ClearTagIdRequest::COMMAND => parse_req!(ClearTagIdRequest, parts),
/* stored playlists */
ListPlaylistRequest::COMMAND => parse_req!(ListPlaylistRequest, parts),
ListPlaylistInfoRequest::COMMAND => parse_req!(ListPlaylistInfoRequest, parts),
SearchPlaylistRequest::COMMAND => parse_req!(SearchPlaylistRequest, parts),
ListPlaylistsRequest::COMMAND => parse_req!(ListPlaylistsRequest, parts),
LoadRequest::COMMAND => parse_req!(LoadRequest, parts),
PlaylistAddRequest::COMMAND => parse_req!(PlaylistAddRequest, parts),
PlaylistClearRequest::COMMAND => parse_req!(PlaylistClearRequest, parts),
PlaylistDeleteRequest::COMMAND => parse_req!(PlaylistDeleteRequest, parts),
PlaylistLengthRequest::COMMAND => parse_req!(PlaylistLengthRequest, parts),
PlaylistMoveRequest::COMMAND => parse_req!(PlaylistMoveRequest, parts),
RenameRequest::COMMAND => parse_req!(RenameRequest, parts),
RmRequest::COMMAND => parse_req!(RmRequest, parts),
SaveRequest::COMMAND => parse_req!(SaveRequest, parts),
/* music database */
AlbumArtRequest::COMMAND => parse_req!(AlbumArtRequest, parts),
CountRequest::COMMAND => parse_req!(CountRequest, parts),
GetFingerprintRequest::COMMAND => parse_req!(GetFingerprintRequest, parts),
FindRequest::COMMAND => parse_req!(FindRequest, parts),
FindAddRequest::COMMAND => parse_req!(FindAddRequest, parts),
ListRequest::COMMAND => parse_req!(ListRequest, parts),
ListAllRequest::COMMAND => parse_req!(ListAllRequest, parts),
ListAllInfoRequest::COMMAND => parse_req!(ListAllInfoRequest, parts),
ListFilesRequest::COMMAND => parse_req!(ListFilesRequest, parts),
LsInfoRequest::COMMAND => parse_req!(LsInfoRequest, parts),
ReadCommentsRequest::COMMAND => parse_req!(ReadCommentsRequest, parts),
ReadPictureRequest::COMMAND => parse_req!(ReadPictureRequest, parts),
SearchRequest::COMMAND => parse_req!(SearchRequest, parts),
SearchAddRequest::COMMAND => parse_req!(SearchAddRequest, parts),
SearchAddPlRequest::COMMAND => parse_req!(SearchAddPlRequest, parts),
SearchCountRequest::COMMAND => parse_req!(SearchCountRequest, parts),
UpdateRequest::COMMAND => parse_req!(UpdateRequest, parts),
RescanRequest::COMMAND => parse_req!(RescanRequest, parts),
/* mounts and neighbors */
MountRequest::COMMAND => parse_req!(MountRequest, parts),
UnmountRequest::COMMAND => parse_req!(UnmountRequest, parts),
ListMountsRequest::COMMAND => parse_req!(ListMountsRequest, parts),
ListNeighborsRequest::COMMAND => parse_req!(ListNeighborsRequest, parts),
/* stickers */
StickerGetRequest::COMMAND => parse_req!(StickerGetRequest, parts),
StickerSetRequest::COMMAND => parse_req!(StickerSetRequest, parts),
StickerIncRequest::COMMAND => parse_req!(StickerIncRequest, parts),
StickerDecRequest::COMMAND => parse_req!(StickerDecRequest, parts),
StickerDeleteRequest::COMMAND => parse_req!(StickerDeleteRequest, parts),
StickerListRequest::COMMAND => parse_req!(StickerListRequest, parts),
StickerFindRequest::COMMAND => parse_req!(StickerFindRequest, parts),
StickerNamesRequest::COMMAND => parse_req!(StickerNamesRequest, parts),
StickerTypesRequest::COMMAND => parse_req!(StickerTypesRequest, parts),
StickerNamesTypesRequest::COMMAND => parse_req!(StickerNamesTypesRequest, parts),
/* connection settings */
CloseRequest::COMMAND => parse_req!(CloseRequest, parts),
KillRequest::COMMAND => parse_req!(KillRequest, parts),
PasswordRequest::COMMAND => parse_req!(PasswordRequest, parts),
PingRequest::COMMAND => parse_req!(PingRequest, parts),
BinaryLimitRequest::COMMAND => parse_req!(BinaryLimitRequest, parts),
TagTypesRequest::COMMAND => parse_req!(TagTypesRequest, parts),
TagTypesDisableRequest::COMMAND => parse_req!(TagTypesDisableRequest, parts),
TagTypesEnableRequest::COMMAND => parse_req!(TagTypesEnableRequest, parts),
TagTypesClearRequest::COMMAND => parse_req!(TagTypesClearRequest, parts),
TagTypesAllRequest::COMMAND => parse_req!(TagTypesAllRequest, parts),
TagTypesAvailableRequest::COMMAND => parse_req!(TagTypesAvailableRequest, parts),
TagTypesResetRequest::COMMAND => parse_req!(TagTypesResetRequest, parts),
ProtocolRequest::COMMAND => parse_req!(ProtocolRequest, parts),
ProtocolDisableRequest::COMMAND => parse_req!(ProtocolDisableRequest, parts),
ProtocolEnableRequest::COMMAND => parse_req!(ProtocolEnableRequest, parts),
ProtocolClearRequest::COMMAND => parse_req!(ProtocolClearRequest, parts),
ProtocolAllRequest::COMMAND => parse_req!(ProtocolAllRequest, parts),
ProtocolAvailableRequest::COMMAND => parse_req!(ProtocolAvailableRequest, parts),
/* partition commands */
PartitionRequest::COMMAND => parse_req!(PartitionRequest, parts),
ListPartitionsRequest::COMMAND => parse_req!(ListPartitionsRequest, parts),
NewPartitionRequest::COMMAND => parse_req!(NewPartitionRequest, parts),
DelPartitionRequest::COMMAND => parse_req!(DelPartitionRequest, parts),
MoveOutputRequest::COMMAND => parse_req!(MoveOutputRequest, parts),
/* audio output devices */
DisableOutputRequest::COMMAND => parse_req!(DisableOutputRequest, parts),
EnableOutputRequest::COMMAND => parse_req!(EnableOutputRequest, parts),
ToggleOutputRequest::COMMAND => parse_req!(ToggleOutputRequest, parts),
OutputsRequest::COMMAND => parse_req!(OutputsRequest, parts),
OutputSetRequest::COMMAND => parse_req!(OutputSetRequest, parts),
/* reflection */
ConfigRequest::COMMAND => parse_req!(ConfigRequest, parts),
CommandsRequest::COMMAND => parse_req!(CommandsRequest, parts),
NotCommandsRequest::COMMAND => parse_req!(NotCommandsRequest, parts),
UrlHandlersRequest::COMMAND => parse_req!(UrlHandlersRequest, parts),
DecodersRequest::COMMAND => parse_req!(DecodersRequest, parts),
/* client to client */
SubscribeRequest::COMMAND => parse_req!(SubscribeRequest, parts),
UnsubscribeRequest::COMMAND => parse_req!(UnsubscribeRequest, parts),
ChannelsRequest::COMMAND => parse_req!(ChannelsRequest, parts),
ReadMessagesRequest::COMMAND => parse_req!(ReadMessagesRequest, parts),
SendMessageRequest::COMMAND => parse_req!(SendMessageRequest, parts),
_ => unimplemented!(),
}
}
}
-246
View File
@@ -1,246 +0,0 @@
use crate::{Request, Response, types::SubSystem};
pub trait MpdServer {
type Error;
fn route_request(&mut self, request: Request) -> Result<Response, Self::Error> {
match request {
Request::ClearError => self.handle_clear_error().map(|_| Ok(())),
Request::CurrentSong => self.handle_current_song().map(|_| Ok(())),
Request::Idle(subsystems) => self.handle_idle(subsystems).map(|_| Ok(())),
Request::Status => self.handle_status().map(|_| Ok(())),
Request::Stats => self.handle_stats().map(|_| Ok(())),
_ => unimplemented!(),
}
}
fn handle_unimplemented(&mut self) -> Result<(), Self::Error> {
// fn handle_unimplemented(&mut self, name: &str) -> Result<(), Self::Error> {
// return Err("a".into());
unimplemented!()
}
// -- Query Commands -- //
fn handle_clear_error(&mut self) -> Result<(), Self::Error> {
self.handle_unimplemented()
}
fn handle_current_song(&mut self) -> Result<(), Self::Error> {
self.handle_unimplemented()
}
fn handle_idle(&mut self, _: Option<Vec<SubSystem>>) -> Result<(), Self::Error> {
self.handle_unimplemented()
}
fn handle_status(&mut self) -> Result<(), Self::Error> {
self.handle_unimplemented()
}
fn handle_stats(&mut self) -> Result<(), Self::Error> {
self.handle_unimplemented()
}
// -- Playback Commands -- //
// handle_consume(ConsumeState),
// handle_crossfade(Seconds),
// handle_mix_ramp_db(f32),
// handle_mix_ramp_delay(Seconds),
// handle_random(bool),
// handle_repeat(bool),
// handle_set_vol(Volume),
// handle_get_vol,
// handle_single(SingleState),
// handle_replay_gain_mode(ReplayGainMode),
// handle_replay_gain_status,
// handle_volume(Volume),
// // -- Playback Control Commands -- //
// next,
// pause(Option<bool>),
// play(SongPosition),
// play_id(SongId),
// previous,
// seek(SongPosition, TimeWithFractions),
// seek_id(SongId, TimeWithFractions),
// seek_cur(SeekMode, TimeWithFractions),
// stop,
// // -- Queue Commands -- //
// handle_add(String, Option<SongPosition>),
// handle_add_id(String, Option<SongPosition>),
// handle_clear,
// handle_delete(OneOrRange),
// handle_delete_id(SongId),
// handle_move(OneOrRange, SongPosition),
// handle_move_id(SongId, SongPosition),
// handle_playlist,
// handle_playlist_find(Filter, Option<Sort>, Option<WindowRange>),
// handle_playlist_id(SongId),
// handle_playlist_info(OneOrRange),
// handle_playlist_search(Filter, Option<Sort>, Option<WindowRange>),
// handle_pl_changes(Version, Option<WindowRange>),
// handle_pl_changes_pos_id(Version, Option<WindowRange>),
// handle_prio(Priority, WindowRange),
// handle_prio_id(Priority, Vec<SongId>),
// handle_range_id(SongId, WindowRange),
// handle_shuffle(Option<OneOrRange>),
// handle_swap(SongPosition, SongPosition),
// handle_swap_id(SongId, SongId),
// handle_add_tag_id(SongId, TagName, TagValue),
// handle_clear_tag_id(SongId, TagName),
// // -- Stored Playlist Commands -- //
// ListPlaylist(PlaylistName, Option<WindowRange>),
// ListPlaylistInfo(PlaylistName, Option<WindowRange>),
// SearchPlaylist(PlaylistName, Filter, Option<WindowRange>),
// ListPlaylists,
// Load(PlaylistName, Option<WindowRange>, SongPosition),
// PlaylistAdd(PlaylistName, Uri, SongPosition),
// PlaylistClear(PlaylistName),
// PlaylistDelete(PlaylistName, OneOrRange),
// PlaylistLength(PlaylistName),
// // TODO: which type of range?
// PlaylistMove(PlaylistName, OneOrRange, SongPosition),
// Rename(PlaylistName, PlaylistName),
// Rm(PlaylistName),
// Save(PlaylistName, Option<SaveMode>),
// // -- Music Database Commands -- //
// AlbumArt(Uri, Offset),
// Count(Filter, Option<GroupType>),
// GetFingerprint(Uri),
// Find(Filter, Option<Sort>, Option<WindowRange>),
// FindAdd(Filter, Option<Sort>, Option<WindowRange>, Option<SongPosition>),
// List(Tag, Filter, Option<GroupType>),
// #[deprecated]
// ListAll(Option<Uri>),
// #[deprecated]
// ListAllInfo(Option<Uri>),
// ListFiles(Uri),
// LsInfo(Option<Uri>),
// ReadComments(Uri),
// ReadPicture(Uri, Offset),
// Search(Filter, Option<Sort>, Option<WindowRange>),
// SearchAdd(Filter, Option<Sort>, Option<WindowRange>, Option<SongPosition>),
// SearchAddPl(Filter, Option<Sort>, Option<WindowRange>, Option<SongPosition>),
// SearchCount(Filter, Option<GroupType>),
// Update(Option<Uri>),
// Rescan(Option<Uri>),
// // -- Mount and Neighbor Commands -- //
// Mount(Option<Path>, Option<Uri>),
// Unmount(Path),
// ListMounts,
// ListNeighbors,
// // -- Sticker Commands -- //
// StickerGet(StickerType, Uri, String),
// StickerSet(StickerType, Uri, String, String),
// StickerDelete(StickerType, Uri, String),
// StickerList(StickerType, Uri),
// StickerFind(StickerType, Uri, String, Option<Sort>, Option<WindowRange>),
// StickerFindValue(StickerType, Uri, String, String, Option<Sort>, Option<WindowRange>),
// StickerNames,
// StickerTypes,
// StickerNamesTypes(Option<StickerType>),
// // -- Connection Commands -- //
// Close,
// Kill,
// Password(String),
// Ping,
// BinaryLimit(u64),
// TagTypes,
// TagTypesDisable(Vec<Tag>),
// TagTypesEnable(Vec<Tag>),
// TagTypesClear,
// TagTypesAll,
// TagTypesAvailable,
// TagTypesReset(Vec<Tag>),
// Protocol,
// ProtocolDisable(Vec<Feature>),
// ProtocolEnable(Vec<Feature>),
// ProtocolClear,
// ProtocolAll,
// ProtocolAvailable,
// // -- Partition Commands -- //
// Partition(PartitionName),
// ListPartitions,
// NewPartition(PartitionName),
// DelPartition(PartitionName),
// MoveOutput(String),
// // -- Audio Output Commands -- //
// DisableOutput(AudioOutputId),
// EnableOutput(AudioOutputId),
// ToggleOutput(AudioOutputId),
// Outputs,
// OutputSet(AudioOutputId, String, String),
// // -- Reflection Commands -- //
// Config,
// Commands,
// NotCommands,
// UrlHandlers,
// Decoders,
// // -- Client to Client Commands -- //
// Subscribe(ChannelName),
// Unsubscribe(ChannelName),
// Channels,
// ReadMessages,
// SendMessage(ChannelName, String),
}
// impl Into<Vec<u8>> for Request {
// fn into(self) -> Vec<u8> {
// todo!()
// }
// }
// #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
// pub enum SaveMode {
// Create,
// Append,
// Replace,
// }
// #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
// pub enum SeekMode {
// Relative,
// RelativeReverse,
// Absolute,
// }
// #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
// pub enum SubSystem {
// /// The song database has been modified after update.
// Database,
// /// A database update has started or finished. If the database was modified during the update, the database event is also emitted.
// Update,
// /// A stored playlist has been modified, renamed, created or deleted
// StoredPlaylist,
// /// The queue (i.e. the current playlist) has been modified
// Playlist,
// /// The player has been started, stopped or seeked or tags of the currently playing song have changed (e.g. received from stream)
// Player,
// /// The volume has been changed
// Mixer,
// /// An audio output has been added, removed or modified (e.g. renamed, enabled or disabled)
// Output,
// /// Options like repeat, random, crossfade, replay gain
// Options,
// /// A partition was added, removed or changed
// Partition,
// /// The sticker database has been modified.
// Sticker,
// /// A client has subscribed or unsubscribed to a channel
// Subscription,
// /// A message was received on a channel this client is subscribed to; this event is only emitted when the clients message queue is empty
// Message,
// /// A neighbor was found or lost
// Neighbor,
// /// The mount list has changed
// Mount,
// /// Other subsystems not covered by the above
// Other(String),
// }