commands: add command executor directly on Command trait

This commit is contained in:
2025-12-08 13:05:30 +09:00
parent 10fb43fa64
commit f2e2eb271a

View File

@@ -37,6 +37,16 @@ pub use reflection::*;
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 trait CommandRequest
where
@@ -159,6 +169,55 @@ 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