Implement some more commands
This commit is contained in:
parent
abacb54c8d
commit
9cef59eb88
@ -16,6 +16,7 @@ mod playback_options;
|
|||||||
mod querying_mpd_status;
|
mod querying_mpd_status;
|
||||||
mod queue;
|
mod queue;
|
||||||
mod reflection;
|
mod reflection;
|
||||||
|
mod stickers;
|
||||||
mod stored_playlists;
|
mod stored_playlists;
|
||||||
|
|
||||||
pub use audio_output_devices::*;
|
pub use audio_output_devices::*;
|
||||||
@ -29,6 +30,7 @@ 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 reflection::*;
|
||||||
|
pub use stickers::*;
|
||||||
pub use stored_playlists::*;
|
pub use stored_playlists::*;
|
||||||
|
|
||||||
pub trait Command {
|
pub trait Command {
|
||||||
|
21
src/commands/stickers.rs
Normal file
21
src/commands/stickers.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
pub mod sticker_dec;
|
||||||
|
pub mod sticker_delete;
|
||||||
|
pub mod sticker_find;
|
||||||
|
pub mod sticker_get;
|
||||||
|
pub mod sticker_inc;
|
||||||
|
pub mod sticker_list;
|
||||||
|
pub mod sticker_set;
|
||||||
|
pub mod stickernames;
|
||||||
|
pub mod stickernamestypes;
|
||||||
|
pub mod stickertypes;
|
||||||
|
|
||||||
|
pub use sticker_dec::StickerDec;
|
||||||
|
pub use sticker_delete::StickerDelete;
|
||||||
|
pub use sticker_find::StickerFind;
|
||||||
|
pub use sticker_get::StickerGet;
|
||||||
|
pub use sticker_inc::StickerInc;
|
||||||
|
pub use sticker_list::StickerList;
|
||||||
|
pub use sticker_set::StickerSet;
|
||||||
|
pub use stickernames::StickerNames;
|
||||||
|
pub use stickernamestypes::StickerNamesTypes;
|
||||||
|
pub use stickertypes::StickerTypes;
|
45
src/commands/stickers/sticker_dec.rs
Normal file
45
src/commands/stickers/sticker_dec.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerDec;
|
||||||
|
|
||||||
|
impl Command for StickerDec {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "sticker dec";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let sticker_type = sticker_type
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
|
||||||
|
|
||||||
|
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let uri = uri
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
|
||||||
|
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
|
||||||
|
|
||||||
|
let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let value = value
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, value.to_owned()))?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerDec(sticker_type, uri, name, value), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
40
src/commands/stickers/sticker_delete.rs
Normal file
40
src/commands/stickers/sticker_delete.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerDelete;
|
||||||
|
|
||||||
|
impl Command for StickerDelete {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "sticker delete";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let sticker_type = sticker_type
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
|
||||||
|
|
||||||
|
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let uri = uri
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
|
||||||
|
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerDelete(sticker_type, uri, name), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
120
src/commands/stickers/sticker_find.rs
Normal file
120
src/commands/stickers/sticker_find.rs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserError, RequestParserResult,
|
||||||
|
ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerFind;
|
||||||
|
|
||||||
|
pub struct StickerFindResponseEntry {
|
||||||
|
pub uri: String,
|
||||||
|
pub name: String,
|
||||||
|
pub value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type StickerFindResponse = Vec<StickerFindResponseEntry>;
|
||||||
|
|
||||||
|
impl Command for StickerFind {
|
||||||
|
type Response = StickerFindResponse;
|
||||||
|
const COMMAND: &'static str = "sticker find";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let sticker_type = sticker_type
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
|
||||||
|
|
||||||
|
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let uri = uri
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
|
||||||
|
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
|
||||||
|
|
||||||
|
// TODO: handle the case for this command as well:
|
||||||
|
// sticker find {TYPE} {URI} {NAME} = {VALUE} [sort {SORTTYPE}] [window {START:END}]
|
||||||
|
|
||||||
|
let mut sort_or_window = parts.next();
|
||||||
|
let mut sort = None;
|
||||||
|
if let Some("sort") = sort_or_window {
|
||||||
|
sort = Some(
|
||||||
|
parts
|
||||||
|
.next()
|
||||||
|
.ok_or(RequestParserError::UnexpectedEOF)?
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
sort_or_window = parts.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut window = None;
|
||||||
|
if let Some("window") = sort_or_window {
|
||||||
|
let w = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
window = Some(
|
||||||
|
w.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(0, w.to_string()))?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
Request::StickerFind(sticker_type, uri, name, sort, window),
|
||||||
|
"",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: Vec<_> = parts.into();
|
||||||
|
let mut stickers = Vec::new();
|
||||||
|
|
||||||
|
for sticker_uri_pair in parts.chunks_exact(2) {
|
||||||
|
// TODO: don't assume that the order of the properties is fixed
|
||||||
|
let uri = sticker_uri_pair
|
||||||
|
.first()
|
||||||
|
.ok_or(ResponseParserError::UnexpectedEOF)?;
|
||||||
|
let sticker = sticker_uri_pair
|
||||||
|
.get(1)
|
||||||
|
.ok_or(ResponseParserError::UnexpectedEOF)?;
|
||||||
|
|
||||||
|
debug_assert!(sticker.0 == "sticker");
|
||||||
|
// TODO: debug assert that this is a valid sticker type
|
||||||
|
// debug_assert!(uri.0 == "");
|
||||||
|
|
||||||
|
let uri = match uri.1 {
|
||||||
|
GenericResponseValue::Text(s) => s.to_string(),
|
||||||
|
GenericResponseValue::Binary(_) => {
|
||||||
|
return Err(ResponseParserError::UnexpectedPropertyType(uri.0, "Binary"))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let sticker = match sticker.1 {
|
||||||
|
GenericResponseValue::Text(s) => s,
|
||||||
|
GenericResponseValue::Binary(_) => {
|
||||||
|
return Err(ResponseParserError::UnexpectedPropertyType(
|
||||||
|
"sticker", "Binary",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: This assumes the first = is the only one.
|
||||||
|
// See: https://github.com/MusicPlayerDaemon/MPD/issues/2166
|
||||||
|
let mut split = sticker.split("=");
|
||||||
|
let name = split
|
||||||
|
.next()
|
||||||
|
.ok_or(ResponseParserError::SyntaxError(0, sticker))?
|
||||||
|
.to_string();
|
||||||
|
let value = split
|
||||||
|
.next()
|
||||||
|
.ok_or(ResponseParserError::SyntaxError(1, sticker))?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
stickers.push(StickerFindResponseEntry { uri, name, value });
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(stickers)
|
||||||
|
}
|
||||||
|
}
|
57
src/commands/stickers/sticker_get.rs
Normal file
57
src/commands/stickers/sticker_get.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserError, RequestParserResult,
|
||||||
|
ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerGet;
|
||||||
|
|
||||||
|
pub type StickerGetResponse = String;
|
||||||
|
|
||||||
|
impl Command for StickerGet {
|
||||||
|
type Response = StickerGetResponse;
|
||||||
|
const COMMAND: &'static str = "sticker get";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let sticker_type = sticker_type
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
|
||||||
|
|
||||||
|
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let uri = uri
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
|
||||||
|
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerGet(sticker_type, uri, name), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: Vec<_> = parts.into();
|
||||||
|
let mut parts = parts.into_iter();
|
||||||
|
let sticker = parts.next().ok_or(ResponseParserError::UnexpectedEOF)?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
debug_assert!(sticker.0 == "sticker");
|
||||||
|
|
||||||
|
let sticker = match sticker.1 {
|
||||||
|
GenericResponseValue::Text(s) => s.to_string(),
|
||||||
|
GenericResponseValue::Binary(_) => {
|
||||||
|
return Err(ResponseParserError::UnexpectedPropertyType(
|
||||||
|
"sticker", "Binary",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(sticker)
|
||||||
|
}
|
||||||
|
}
|
45
src/commands/stickers/sticker_inc.rs
Normal file
45
src/commands/stickers/sticker_inc.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerInc;
|
||||||
|
|
||||||
|
impl Command for StickerInc {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "sticker inc";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let sticker_type = sticker_type
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
|
||||||
|
|
||||||
|
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let uri = uri
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
|
||||||
|
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
|
||||||
|
|
||||||
|
let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let value = value
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, value.to_owned()))?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerInc(sticker_type, uri, name, value), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
60
src/commands/stickers/sticker_list.rs
Normal file
60
src/commands/stickers/sticker_list.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserError, RequestParserResult,
|
||||||
|
ResponseAttributes, ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerList;
|
||||||
|
|
||||||
|
pub type StickerListResponse = HashMap<String, String>;
|
||||||
|
|
||||||
|
impl Command for StickerList {
|
||||||
|
type Response = StickerListResponse;
|
||||||
|
const COMMAND: &'static str = "sticker list";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let sticker_type = sticker_type
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, "sticker_type".to_owned()))?;
|
||||||
|
|
||||||
|
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let uri = uri
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, "uri".to_owned()))?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerList(sticker_type, uri), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: Vec<_> = parts.into();
|
||||||
|
debug_assert!(parts.iter().all(|(k, _)| *k == "sticker"));
|
||||||
|
|
||||||
|
let result = parts
|
||||||
|
.iter()
|
||||||
|
.map(|(_, v)| match v {
|
||||||
|
GenericResponseValue::Text(value) => Ok(value),
|
||||||
|
GenericResponseValue::Binary(_) => Err(
|
||||||
|
ResponseParserError::UnexpectedPropertyType("sticker", "Binary"),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, ResponseParserError>>()?;
|
||||||
|
|
||||||
|
result
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| {
|
||||||
|
// TODO: This assumes the first = is the only one.
|
||||||
|
// See: https://github.com/MusicPlayerDaemon/MPD/issues/2166
|
||||||
|
let mut split = v.split('=');
|
||||||
|
let key = split.next().ok_or(ResponseParserError::SyntaxError(0, v))?;
|
||||||
|
let value = split.next().ok_or(ResponseParserError::SyntaxError(1, v))?;
|
||||||
|
Ok((key.to_string(), value.to_string()))
|
||||||
|
})
|
||||||
|
.collect::<Result<HashMap<_, _>, ResponseParserError>>()
|
||||||
|
}
|
||||||
|
}
|
45
src/commands/stickers/sticker_set.rs
Normal file
45
src/commands/stickers/sticker_set.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerSet;
|
||||||
|
|
||||||
|
impl Command for StickerSet {
|
||||||
|
type Response = ();
|
||||||
|
const COMMAND: &'static str = "sticker set";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let sticker_type = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let sticker_type = sticker_type
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, sticker_type.to_owned()))?;
|
||||||
|
|
||||||
|
let uri = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let uri = uri
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, uri.to_owned()))?;
|
||||||
|
|
||||||
|
let name = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let name = name
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, name.to_owned()))?;
|
||||||
|
|
||||||
|
let value = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
|
||||||
|
let value = value
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| RequestParserError::SyntaxError(1, value.to_owned()))?;
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerSet(sticker_type, uri, name, value), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.is_empty());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
38
src/commands/stickers/stickernames.rs
Normal file
38
src/commands/stickers/stickernames.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerNames;
|
||||||
|
|
||||||
|
pub type StickerNamesResponse = Vec<String>;
|
||||||
|
|
||||||
|
impl Command for StickerNames {
|
||||||
|
type Response = StickerNamesResponse;
|
||||||
|
const COMMAND: &'static str = "stickernames";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerNames, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.0.iter().all(|(k, _)| *k == "name"));
|
||||||
|
|
||||||
|
let list = parts
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|(_, v)| match v {
|
||||||
|
GenericResponseValue::Text(value) => Ok(value.to_string()),
|
||||||
|
GenericResponseValue::Binary(_) => Err(
|
||||||
|
ResponseParserError::UnexpectedPropertyType("name", "Binary"),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, ResponseParserError>>()?;
|
||||||
|
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
}
|
63
src/commands/stickers/stickernamestypes.rs
Normal file
63
src/commands/stickers/stickernamestypes.rs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerNamesTypes;
|
||||||
|
|
||||||
|
pub type StickerNamesTypesResponse = HashMap<String, Vec<String>>;
|
||||||
|
|
||||||
|
impl Command for StickerNamesTypes {
|
||||||
|
type Response = StickerNamesTypesResponse;
|
||||||
|
const COMMAND: &'static str = "stickernamestypes";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
let sticker_type = parts.next().map(|s| s.to_string());
|
||||||
|
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerNamesTypes(sticker_type), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
let parts: Vec<_> = parts.into();
|
||||||
|
let mut result = HashMap::new();
|
||||||
|
|
||||||
|
for name_type_pair in parts.chunks_exact(2) {
|
||||||
|
// TODO: don't depend on order, just make sure we have both
|
||||||
|
let (name_key, name_value) = name_type_pair[0];
|
||||||
|
let (type_key, type_value) = name_type_pair[1];
|
||||||
|
debug_assert!(name_key == "name");
|
||||||
|
debug_assert!(type_key == "type");
|
||||||
|
|
||||||
|
let name = match name_value {
|
||||||
|
GenericResponseValue::Text(s) => s.to_string(),
|
||||||
|
GenericResponseValue::Binary(_) => {
|
||||||
|
return Err(ResponseParserError::UnexpectedPropertyType(
|
||||||
|
"name", "Binary",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let sticker_type = match type_value {
|
||||||
|
GenericResponseValue::Text(s) => s.to_string(),
|
||||||
|
GenericResponseValue::Binary(_) => {
|
||||||
|
return Err(ResponseParserError::UnexpectedPropertyType(
|
||||||
|
"type", "Binary",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
result
|
||||||
|
.entry(name)
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(sticker_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
38
src/commands/stickers/stickertypes.rs
Normal file
38
src/commands/stickers/stickertypes.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use crate::commands::{
|
||||||
|
Command, GenericResponseValue, Request, RequestParserResult, ResponseAttributes,
|
||||||
|
ResponseParserError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StickerTypes;
|
||||||
|
|
||||||
|
pub type StickerTypesResponse = Vec<String>;
|
||||||
|
|
||||||
|
impl Command for StickerTypes {
|
||||||
|
type Response = StickerTypesResponse;
|
||||||
|
const COMMAND: &'static str = "stickertypes";
|
||||||
|
|
||||||
|
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
|
||||||
|
debug_assert!(parts.next().is_none());
|
||||||
|
|
||||||
|
Ok((Request::StickerTypes, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_response(
|
||||||
|
parts: ResponseAttributes<'_>,
|
||||||
|
) -> Result<Self::Response, ResponseParserError> {
|
||||||
|
debug_assert!(parts.0.iter().all(|(k, _)| *k == "stickertype"));
|
||||||
|
|
||||||
|
let list = parts
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.map(|(_, v)| match v {
|
||||||
|
GenericResponseValue::Text(value) => Ok(value.to_string()),
|
||||||
|
GenericResponseValue::Binary(_) => Err(
|
||||||
|
ResponseParserError::UnexpectedPropertyType("stickertype", "Binary"),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, ResponseParserError>>()?;
|
||||||
|
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
}
|
@ -139,6 +139,8 @@ pub enum Request {
|
|||||||
// -- Sticker Commands -- //
|
// -- Sticker Commands -- //
|
||||||
StickerGet(StickerType, Uri, String),
|
StickerGet(StickerType, Uri, String),
|
||||||
StickerSet(StickerType, Uri, String, String),
|
StickerSet(StickerType, Uri, String, String),
|
||||||
|
StickerInc(StickerType, Uri, String, usize),
|
||||||
|
StickerDec(StickerType, Uri, String, usize),
|
||||||
StickerDelete(StickerType, Uri, String),
|
StickerDelete(StickerType, Uri, String),
|
||||||
StickerList(StickerType, Uri),
|
StickerList(StickerType, Uri),
|
||||||
StickerFind(StickerType, Uri, String, Option<Sort>, Option<WindowRange>),
|
StickerFind(StickerType, Uri, String, Option<Sort>, Option<WindowRange>),
|
||||||
@ -475,6 +477,16 @@ impl Request {
|
|||||||
ListNeighbors::COMMAND => ListNeighbors::parse_request(parts),
|
ListNeighbors::COMMAND => ListNeighbors::parse_request(parts),
|
||||||
|
|
||||||
/* stickers */
|
/* stickers */
|
||||||
|
StickerGet::COMMAND => StickerGet::parse_request(parts),
|
||||||
|
StickerSet::COMMAND => StickerSet::parse_request(parts),
|
||||||
|
StickerInc::COMMAND => StickerInc::parse_request(parts),
|
||||||
|
StickerDec::COMMAND => StickerDec::parse_request(parts),
|
||||||
|
StickerDelete::COMMAND => StickerDelete::parse_request(parts),
|
||||||
|
StickerList::COMMAND => StickerList::parse_request(parts),
|
||||||
|
StickerFind::COMMAND => StickerFind::parse_request(parts),
|
||||||
|
StickerNames::COMMAND => StickerNames::parse_request(parts),
|
||||||
|
StickerTypes::COMMAND => StickerTypes::parse_request(parts),
|
||||||
|
StickerNamesTypes::COMMAND => StickerNamesTypes::parse_request(parts),
|
||||||
|
|
||||||
/* connection settings */
|
/* connection settings */
|
||||||
Close::COMMAND => Close::parse_request(parts),
|
Close::COMMAND => Close::parse_request(parts),
|
||||||
|
Loading…
Reference in New Issue
Block a user