async_mpd/client/resp/
handlers.rs1use async_net::TcpStream;
2use async_trait::async_trait;
3
4use futures_lite::io::BufReader;
5use futures_lite::{AsyncBufReadExt, StreamExt};
6
7use std::marker::PhantomData;
8use std::str::FromStr;
9
10use crate::resp::WrappedResponse;
11use crate::{
12 client::resp::{
13 read_resp_line,
14 respmap::RespMap,
15 respmap_handlers::{mixed_stream, tracks, ListallinfoResponse},
16 },
17 Error, Track,
18};
19
20#[async_trait]
21pub trait ResponseHandler: Sized {
23 type Response: Into<WrappedResponse>;
25
26 async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, crate::Error>;
27}
28
29pub struct Tracks;
30
31#[async_trait]
32impl ResponseHandler for Tracks {
33 type Response = Vec<Track>;
34
35 async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, Error> {
36 tracks(reader).await.map_err(Into::into)
37 }
38}
39
40pub struct MixedResponseResponse;
41
42#[async_trait]
43impl ResponseHandler for MixedResponseResponse {
44 type Response = ListallinfoResponse;
45
46 async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, Error> {
47 mixed_stream(reader).await.map_err(Into::into)
48 }
49}
50
51pub struct RespMapResponse<T> {
52 _0: PhantomData<T>,
53}
54
55#[async_trait]
56impl<T: From<RespMap> + Into<WrappedResponse>> ResponseHandler for RespMapResponse<T> {
57 type Response = T;
58
59 async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, Error> {
60 let mut map = RespMap::new();
61 let mut lines = reader.lines();
62
63 while let Some(line) = lines.next().await {
64 let line = line?;
65 log::debug!("line: '{}'", line);
66
67 if &line == "OK" {
68 break;
69 }
70
71 if line.starts_with("ACK ") {
72 return Err(crate::Error::ServerError { msg: line });
73 }
74
75 if let Some((k, v)) = line.split_once(": ") {
76 map.insert(k, v);
77 }
78 }
79
80 Ok(map.into())
81 }
82}
83
84pub struct SingleLineResp<T> {
85 _0: PhantomData<T>,
86}
87
88#[async_trait]
89impl<E: Into<crate::Error>, T: FromStr<Err = E> + Into<WrappedResponse>> ResponseHandler
90 for SingleLineResp<T>
91{
92 type Response = T;
93
94 async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, Error> {
95 let line = read_resp_line(reader).await?;
96
97 let (_key, value) = line.split_once(": ").ok_or(crate::Error::ValueError {msg: "invalid line".to_string() })?;
98
99 T::from_str(value).map_err(Into::into)
100 }
101}
102
103pub struct OkResponse;
104
105#[async_trait]
106impl ResponseHandler for OkResponse {
107 type Response = ();
108
109 async fn handle(reader: &mut BufReader<TcpStream>) -> Result<Self::Response, crate::Error> {
110 let mut lines = reader.lines();
111
112 if let Some(line) = lines.next().await {
113 let line = line?;
114
115 if &line == "OK" {
116 Ok(())
117 } else {
118 Err(crate::Error::ServerError { msg: line })
119 }
120 } else {
121 Ok(())
122 }
123 }
124}