WIP: serialize requests

This commit is contained in:
2025-11-21 16:48:55 +09:00
parent a4b0795121
commit ed82218d4e
132 changed files with 1661 additions and 156 deletions

View File

@@ -1,17 +1,33 @@
use serde::{Deserialize, Serialize};
use crate::{
commands::{
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
ResponseParserError,
},
common::SongPosition,
common::{SongPosition, Uri},
};
pub struct Add;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AddRequest {
uri: Uri,
position: Option<SongPosition>,
}
impl Command for Add {
type Request = AddRequest;
type Response = ();
const COMMAND: &'static str = "add";
fn serialize_request(&self, request: Self::Request) -> String {
match request.position {
Some(position) => format!("{} {} {}", Self::COMMAND, request.uri, position),
None => format!("{} {}", Self::COMMAND, request.uri),
}
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let uri = match parts.next() {
Some(s) => s,

View File

@@ -5,20 +5,34 @@ use crate::{
Command, Request, RequestParserError, RequestParserResult, ResponseAttributes,
ResponseParserError, get_next_and_parse_property,
},
common::{SongId, SongPosition},
common::{SongId, SongPosition, Uri},
};
pub struct AddId;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AddIdRequest {
pub uri: Uri,
pub position: Option<SongPosition>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AddIdResponse {
pub id: SongId,
}
impl Command for AddId {
type Request = AddIdRequest;
type Response = AddIdResponse;
const COMMAND: &'static str = "addid";
fn serialize_request(&self, request: Self::Request) -> String {
match request.position {
Some(pos) => format!("{} {} {}", Self::COMMAND, request.uri, pos),
None => format!("{} {}", Self::COMMAND, request.uri),
}
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let uri = match parts.next() {
Some(s) => s,

View File

@@ -1,16 +1,37 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{SongId, TagName, TagValue},
};
pub struct AddTagId;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AddTagIdRequest {
pub songid: SongId,
pub tag_name: TagName,
pub tag_value: TagValue,
}
impl Command for AddTagId {
type Request = AddTagIdRequest;
type Response = ();
const COMMAND: &'static str = "addtagid";
fn serialize_request(&self, request: Self::Request) -> String {
format!(
"{} {} {} {}",
Self::COMMAND,
request.songid,
request.tag_name,
request.tag_value
)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let songid = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let songid = songid

View File

@@ -5,9 +5,14 @@ use crate::commands::{
pub struct Clear;
impl Command for Clear {
type Request = ();
type Response = ();
const COMMAND: &'static str = "clear";
fn serialize_request(&self, _request: Self::Request) -> String {
Self::COMMAND.to_string()
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
debug_assert!(parts.next().is_none());
Ok((Request::Clear, ""))

View File

@@ -1,16 +1,30 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{SongId, TagName},
};
pub struct ClearTagId;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClearTagIdRequest {
pub songid: SongId,
pub tag_name: TagName,
}
impl Command for ClearTagId {
type Request = ClearTagIdRequest;
type Response = ();
const COMMAND: &'static str = "cleartagid";
fn serialize_request(&self, request: Self::Request) -> String {
format!("{} {} {}", Self::COMMAND, request.songid, request.tag_name)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let songid = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let songid = songid

View File

@@ -11,9 +11,14 @@ use crate::{
pub struct Delete;
impl Command for Delete {
type Request = OneOrRange;
type Response = ();
const COMMAND: &'static str = "delete";
fn serialize_request(&self, request: Self::Request) -> String {
format!("{} {}", Self::COMMAND, request)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let pos_or_range = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let one_or_range = OneOrRange::from_str(pos_or_range)

View File

@@ -3,14 +3,20 @@ use crate::{
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::SongId,
};
pub struct DeleteId;
impl Command for DeleteId {
type Request = SongId;
type Response = ();
const COMMAND: &'static str = "deleteid";
fn serialize_request(&self, request: Self::Request) -> String {
format!("{} {}", Self::COMMAND, request)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let id = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let id = id

View File

@@ -1,16 +1,30 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{AbsouluteRelativeSongPosition, OneOrRange},
};
pub struct Move;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MoveRequest {
pub from_or_range: OneOrRange,
pub to: AbsouluteRelativeSongPosition,
}
impl Command for Move {
type Request = MoveRequest;
type Response = ();
const COMMAND: &'static str = "move";
fn serialize_request(&self, request: Self::Request) -> String {
format!("{} {} {}", Self::COMMAND, request.from_or_range, request.to)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let from_or_range = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let from_or_range = from_or_range

View File

@@ -1,16 +1,30 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{AbsouluteRelativeSongPosition, SongId},
};
pub struct MoveId;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MoveIdRequest {
pub id: SongId,
pub to: AbsouluteRelativeSongPosition,
}
impl Command for MoveId {
type Request = MoveIdRequest;
type Response = ();
const COMMAND: &'static str = "moveid";
fn serialize_request(&self, request: Self::Request) -> String {
format!("{} {} {}", Self::COMMAND, request.id, request.to)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let id = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let id = id

View File

@@ -6,9 +6,14 @@ use crate::{
pub struct Playlist;
impl Command for Playlist {
type Request = ();
type Response = ();
const COMMAND: &'static str = "playlist";
fn serialize_request(&self, _request: Self::Request) -> String {
Self::COMMAND.to_string()
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
debug_assert!(parts.next().is_none());
Ok((Request::Playlist, ""))

View File

@@ -1,17 +1,39 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
filter::parse_filter,
common::{Sort, WindowRange},
filter::{Filter, parse_filter},
};
pub struct PlaylistFind;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PlaylistFindRequest {
filter: Filter,
sort: Option<Sort>,
window: Option<WindowRange>,
}
impl Command for PlaylistFind {
type Request = PlaylistFindRequest;
type Response = ();
const COMMAND: &'static str = "playlistfind";
fn serialize_request(&self, request: Self::Request) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, request.filter);
if let Some(sort) = request.sort {
cmd.push_str(&format!(" sort {}", sort));
}
if let Some(window) = request.window {
cmd.push_str(&format!(" window {}", window));
}
cmd
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let filter = parse_filter(&mut parts)?;

View File

@@ -3,14 +3,20 @@ use crate::{
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::SongId,
};
pub struct PlaylistId;
impl Command for PlaylistId {
type Request = SongId;
type Response = ();
const COMMAND: &'static str = "playlistid";
fn serialize_request(&self, request: Self::Request) -> String {
format!("{} {}", Self::COMMAND, request)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let id = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let id = id

View File

@@ -3,14 +3,23 @@ use crate::{
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::OneOrRange,
};
pub struct PlaylistInfo;
impl Command for PlaylistInfo {
type Request = Option<OneOrRange>;
type Response = ();
const COMMAND: &'static str = "playlistinfo";
fn serialize_request(&self, request: Self::Request) -> String {
match request {
Some(one_or_range) => format!("{} {}", Self::COMMAND, one_or_range),
None => Self::COMMAND.to_string(),
}
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let one_or_range = parts
.next()

View File

@@ -1,17 +1,39 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
filter::parse_filter,
common::{Sort, WindowRange},
filter::{Filter, parse_filter},
};
pub struct PlaylistSearch;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PlaylistSearchRequest {
filter: Filter,
sort: Option<Sort>,
window: Option<WindowRange>,
}
impl Command for PlaylistSearch {
type Request = PlaylistSearchRequest;
type Response = ();
const COMMAND: &'static str = "playlistsearch";
fn serialize_request(&self, request: Self::Request) -> String {
let mut cmd = format!("{} {}", Self::COMMAND, request.filter);
if let Some(sort) = request.sort {
cmd.push_str(&format!(" sort {}", sort));
}
if let Some(window) = request.window {
cmd.push_str(&format!(" window {}", window));
}
cmd
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let filter = parse_filter(&mut parts)?;

View File

@@ -1,16 +1,33 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{Version, WindowRange},
};
pub struct PlChanges;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PlChangesRequest {
pub version: Version,
pub window: Option<WindowRange>,
}
impl Command for PlChanges {
type Request = PlChangesRequest;
type Response = ();
const COMMAND: &'static str = "plchanges";
fn serialize_request(&self, request: Self::Request) -> String {
match request.window {
Some(window) => format!("{} {} {}", Self::COMMAND, request.version, window),
None => format!("{} {}", Self::COMMAND, request.version),
}
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let version = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let version = version

View File

@@ -1,16 +1,33 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{Version, WindowRange},
};
pub struct PlChangesPosId;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PlChangesPosIdRequest {
pub version: Version,
pub window: Option<WindowRange>,
}
impl Command for PlChangesPosId {
type Request = PlChangesPosIdRequest;
type Response = ();
const COMMAND: &'static str = "plchangesposid";
fn serialize_request(&self, request: Self::Request) -> String {
match request.window {
Some(window) => format!("{} {} {}", Self::COMMAND, request.version, window),
None => format!("{} {}", Self::COMMAND, request.version),
}
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let version = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let version = version

View File

@@ -1,16 +1,30 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{Priority, WindowRange},
};
pub struct Prio;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrioRequest {
pub prio: Priority,
pub window: WindowRange,
}
impl Command for Prio {
type Request = PrioRequest;
type Response = ();
const COMMAND: &'static str = "prio";
fn serialize_request(&self, request: Self::Request) -> String {
format!("{} {} {}", Self::COMMAND, request.prio, request.window)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let prio = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let prio = prio

View File

@@ -1,16 +1,36 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{Priority, SongId},
};
pub struct PrioId;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PrioIdRequest {
pub prio: Priority,
pub songids: Vec<SongId>,
}
impl Command for PrioId {
type Request = PrioIdRequest;
type Response = ();
const COMMAND: &'static str = "prioid";
fn serialize_request(&self, request: Self::Request) -> String {
let songids = request
.songids
.iter()
.map(|id| id.to_string())
.collect::<Vec<String>>()
.join(",");
format!("{} {} {}", Self::COMMAND, request.prio, songids)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let prio = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let prio = prio

View File

@@ -1,30 +1,49 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::{SongId, TimeInterval},
};
pub struct RangeId;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RangeIdRequest {
songid: SongId,
time_interval: TimeInterval,
}
impl Command for RangeId {
type Request = RangeIdRequest;
type Response = ();
const COMMAND: &'static str = "rangeid";
fn serialize_request(&self, request: Self::Request) -> String {
format!(
"{} {} {}",
Self::COMMAND,
request.songid,
request.time_interval
)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let songid = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let songid = songid
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, songid.to_string()))?;
let timeinterval = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let timeinterval = timeinterval
let time_interval = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let time_interval = time_interval
.parse()
.map_err(|_| RequestParserError::SyntaxError(0, timeinterval.to_string()))?;
.map_err(|_| RequestParserError::SyntaxError(0, time_interval.to_string()))?;
debug_assert!(parts.next().is_none());
Ok((Request::RangeId(songid, timeinterval), ""))
Ok((Request::RangeId(songid, time_interval), ""))
}
fn parse_response(

View File

@@ -3,14 +3,23 @@ use crate::{
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::OneOrRange,
};
pub struct Shuffle;
impl Command for Shuffle {
type Request = Option<OneOrRange>;
type Response = ();
const COMMAND: &'static str = "shuffle";
fn serialize_request(&self, request: Self::Request) -> String {
match request {
Some(range) => format!("{} {}", Self::COMMAND, range),
None => Self::COMMAND.to_string(),
}
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let range = parts
.next()

View File

@@ -1,16 +1,35 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::SongPosition,
};
pub struct Swap;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SwapRequest {
pub songpos1: SongPosition,
pub songpos2: SongPosition,
}
impl Command for Swap {
type Request = SwapRequest;
type Response = ();
const COMMAND: &'static str = "swap";
fn serialize_request(&self, request: Self::Request) -> String {
format!(
"{} {} {}",
Self::COMMAND,
request.songpos1,
request.songpos2
)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let songpos1 = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let songpos1 = songpos1

View File

@@ -1,16 +1,30 @@
use serde::{Deserialize, Serialize};
use crate::{
Request,
commands::{
Command, RequestParserError, RequestParserResult, ResponseAttributes, ResponseParserError,
},
common::SongId,
};
pub struct SwapId;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SwapIdRequest {
pub songid1: SongId,
pub songid2: SongId,
}
impl Command for SwapId {
type Request = SwapIdRequest;
type Response = ();
const COMMAND: &'static str = "swapid";
fn serialize_request(&self, request: Self::Request) -> String {
format!("{} {} {}", Self::COMMAND, request.songid1, request.songid2)
}
fn parse_request(mut parts: std::str::SplitWhitespace<'_>) -> RequestParserResult<'_> {
let songid1 = parts.next().ok_or(RequestParserError::UnexpectedEOF)?;
let songid1 = songid1