use async_net::TcpStream;
use async_trait::async_trait;
use futures_lite::io::BufReader;
use futures_lite::{AsyncBufReadExt, StreamExt};
use std::marker::PhantomData;
use std::str::FromStr;
use crate::resp::WrappedResponse;
use crate::{
client::resp::{
read_resp_line,
respmap::RespMap,
respmap_handlers::{mixed_stream, tracks, ListallinfoResponse},
},
Error, Track,
};
#[async_trait]
pub trait ResponseHandler: Sized {
type Response: Into<WrappedResponse>;
async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, crate::Error>;
}
pub struct Tracks;
#[async_trait]
impl ResponseHandler for Tracks {
type Response = Vec<Track>;
async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, Error> {
tracks(reader).await.map_err(Into::into)
}
}
pub struct MixedResponseResponse;
#[async_trait]
impl ResponseHandler for MixedResponseResponse {
type Response = ListallinfoResponse;
async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, Error> {
mixed_stream(reader).await.map_err(Into::into)
}
}
pub struct RespMapResponse<T> {
_0: PhantomData<T>,
}
#[async_trait]
impl<T: From<RespMap> + Into<WrappedResponse>> ResponseHandler for RespMapResponse<T> {
type Response = T;
async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, Error> {
let mut map = RespMap::new();
let mut lines = reader.lines();
while let Some(line) = lines.next().await {
let line = line?;
log::debug!("line: '{}'", line);
if &line == "OK" {
break;
}
if line.starts_with("ACK ") {
return Err(crate::Error::ServerError { msg: line });
}
if let Some((k, v)) = line.split_once(": ") {
map.insert(k, v);
}
}
Ok(map.into())
}
}
pub struct SingleLineResp<T> {
_0: PhantomData<T>,
}
#[async_trait]
impl<E: Into<crate::Error>, T: FromStr<Err = E> + Into<WrappedResponse>> ResponseHandler
for SingleLineResp<T>
{
type Response = T;
async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, Error> {
let line = read_resp_line(reader).await?;
let (_key, value) = line.split_once(": ").ok_or(crate::Error::ValueError {msg: "invalid line".to_string() })?;
T::from_str(value).map_err(Into::into)
}
}
pub struct OkResponse;
#[async_trait]
impl ResponseHandler for OkResponse {
type Response = ();
async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, crate::Error> {
let mut lines = reader.lines();
if let Some(line) = lines.next().await {
let line = line?;
if &line == "OK" {
Ok(())
} else {
Err(crate::Error::ServerError { msg: line })
}
} else {
Ok(())
}
}
}