mpd/
proto.rs

1// Hidden internal interface
2#![allow(missing_docs)]
3
4use bufstream::BufStream;
5
6use crate::convert::FromIter;
7use crate::error::{Error, ParseError, ProtoError, Result};
8use crate::reply::Reply;
9
10use std::fmt;
11use std::io::{self, Lines, Read, Write};
12use std::result::Result as StdResult;
13use std::str::FromStr;
14
15pub struct Pairs<I>(pub I);
16
17impl<I> Iterator for Pairs<I>
18where I: Iterator<Item = io::Result<String>>
19{
20    type Item = Result<(String, String)>;
21    fn next(&mut self) -> Option<Result<(String, String)>> {
22        let reply: Option<Result<Reply>> =
23            self.0.next().map(|v| v.map_err(Error::Io).and_then(|s| s.parse::<Reply>().map_err(Error::Parse)));
24        match reply {
25            Some(Ok(Reply::Pair(a, b))) => Some(Ok((a, b))),
26            None | Some(Ok(Reply::Ok)) => None,
27            Some(Ok(Reply::Ack(e))) => Some(Err(Error::Server(e))),
28            Some(Err(e)) => Some(Err(e)),
29        }
30    }
31}
32
33pub struct Maps<'a, I: 'a> {
34    pairs: &'a mut Pairs<I>,
35    sep: &'a str,
36    value: Option<String>,
37    done: bool,
38    first: bool,
39}
40
41impl<'a, I> Iterator for Maps<'a, I>
42where I: Iterator<Item = io::Result<String>>
43{
44    type Item = Result<Vec<(String, String)>>;
45    fn next(&mut self) -> Option<Result<Vec<(String, String)>>> {
46        if self.done {
47            return None;
48        }
49
50        let mut map = Vec::new();
51
52        if let Some(b) = self.value.take() {
53            map.push((self.sep.to_owned(), b));
54        }
55
56        loop {
57            match self.pairs.next() {
58                Some(Ok((a, b))) => {
59                    if &*a == self.sep {
60                        self.value = Some(b);
61                        if self.first {
62                            self.first = false;
63                            return self.next();
64                        }
65                        break;
66                    } else {
67                        map.push((a, b));
68                    }
69                }
70                Some(Err(e)) => return Some(Err(e)),
71                None => {
72                    self.done = true;
73                    break;
74                }
75            }
76        }
77
78        if map.is_empty() {
79            None
80        } else {
81            Some(Ok(map))
82        }
83    }
84}
85
86impl<I> Pairs<I>
87where I: Iterator<Item = io::Result<String>>
88{
89    pub fn split<'a, 'b: 'a>(&'a mut self, f: &'b str) -> Maps<'a, I> {
90        Maps { pairs: self, sep: f, value: None, done: false, first: true }
91    }
92}
93
94// Client inner communication methods {{{
95#[doc(hidden)]
96pub trait Proto {
97    type Stream: Read + Write;
98
99    fn read_bytes(&mut self, bytes: usize) -> Result<Vec<u8>>;
100    fn read_line(&mut self) -> Result<String>;
101    fn read_pairs(&mut self) -> Pairs<Lines<&mut BufStream<Self::Stream>>>;
102
103    fn run_command<I>(&mut self, command: &str, arguments: I) -> Result<()>
104    where I: ToArguments;
105
106    fn read_structs<'a, T>(&'a mut self, key: &'static str) -> Result<Vec<T>>
107    where T: 'a + FromIter {
108        self.read_pairs().split(key).map(|v| v.and_then(|v| FromIter::from_iter(v.into_iter().map(Ok)))).collect()
109    }
110
111    fn read_list(&mut self, key: &'static str) -> Result<Vec<String>> {
112        self.read_pairs().filter(|r| r.as_ref().map(|(a, _)| *a == key).unwrap_or(true)).map(|r| r.map(|(_, b)| b)).collect()
113    }
114
115    fn read_struct<'a, T>(&'a mut self) -> Result<T>
116    where
117        T: 'a + FromIter,
118        Self::Stream: 'a,
119    {
120        FromIter::from_iter(self.read_pairs())
121    }
122
123    fn drain(&mut self) -> Result<()> {
124        loop {
125            let reply = self.read_line()?;
126            match &*reply {
127                "OK" | "list_OK" => break,
128                _ => (),
129            }
130        }
131        Ok(())
132    }
133
134    fn expect_ok(&mut self) -> Result<()> {
135        let line = self.read_line()?;
136
137        match line.parse::<Reply>() {
138            Ok(Reply::Ok) => Ok(()),
139            Ok(Reply::Ack(e)) => Err(Error::Server(e)),
140            Ok(_) => Err(Error::Proto(ProtoError::NotOk)),
141            Err(e) => Err(From::from(e)),
142        }
143    }
144
145    fn read_pair(&mut self) -> Result<(String, String)> {
146        let line = self.read_line()?;
147
148        match line.parse::<Reply>() {
149            Ok(Reply::Pair(a, b)) => Ok((a, b)),
150            Ok(Reply::Ok) => Err(Error::Proto(ProtoError::NotPair)),
151            Ok(Reply::Ack(e)) => Err(Error::Server(e)),
152            Err(e) => Err(Error::Parse(e)),
153        }
154    }
155
156    fn read_field<T: FromStr>(&mut self, field: &'static str) -> Result<T>
157    where ParseError: From<T::Err> {
158        let (a, b) = self.read_pair()?;
159        self.expect_ok()?;
160        if &*a == field {
161            Ok(b.parse::<T>().map_err(Into::<ParseError>::into)?)
162        } else {
163            Err(Error::Proto(ProtoError::NoField(field)))
164        }
165    }
166}
167
168pub trait ToArguments {
169    fn to_arguments<F, E>(&self, _: &mut F) -> StdResult<(), E>
170    where F: FnMut(&str) -> StdResult<(), E>;
171}
172
173impl ToArguments for () {
174    fn to_arguments<F, E>(&self, _: &mut F) -> StdResult<(), E>
175    where F: FnMut(&str) -> StdResult<(), E> {
176        Ok(())
177    }
178}
179
180impl<'a> ToArguments for &'a str {
181    fn to_arguments<F, E>(&self, f: &mut F) -> StdResult<(), E>
182    where F: FnMut(&str) -> StdResult<(), E> {
183        f(self)
184    }
185}
186
187macro_rules! argument_for_display {
188    ( $x:path ) => {
189        impl ToArguments for $x {
190            fn to_arguments<F, E>(&self, f: &mut F) -> StdResult<(), E>
191            where F: FnMut(&str) -> StdResult<(), E> {
192                f(&self.to_string())
193            }
194        }
195    };
196}
197argument_for_display! {i8}
198argument_for_display! {u8}
199argument_for_display! {u32}
200argument_for_display! {f32}
201argument_for_display! {f64}
202argument_for_display! {usize}
203argument_for_display! {crate::status::ReplayGain}
204argument_for_display! {String}
205argument_for_display! {crate::song::Id}
206argument_for_display! {crate::song::Range}
207argument_for_display! {crate::message::Channel}
208
209macro_rules! argument_for_tuple {
210    ( $($t:ident: $T: ident),+ ) => {
211        impl<$($T : ToArguments,)*> ToArguments for ($($T,)*) {
212            fn to_arguments<F, E>(&self, f: &mut F) -> StdResult<(), E>
213                where F: FnMut(&str) -> StdResult<(), E>
214                {
215                    let ($(ref $t,)*) = *self;
216                    $(
217                        $t.to_arguments(f)?;
218                     )*
219                    Ok(())
220                }
221        }
222    };
223}
224argument_for_tuple! {t0: T0}
225argument_for_tuple! {t0: T0, t1: T1}
226argument_for_tuple! {t0: T0, t1: T1, t2: T2}
227argument_for_tuple! {t0: T0, t1: T1, t2: T2, t3: T3}
228argument_for_tuple! {t0: T0, t1: T1, t2: T2, t3:T3, t4: T4}
229
230impl<'a, T: ToArguments> ToArguments for &'a [T] {
231    fn to_arguments<F, E>(&self, f: &mut F) -> StdResult<(), E>
232    where F: FnMut(&str) -> StdResult<(), E> {
233        for arg in *self {
234            arg.to_arguments(f)?
235        }
236        Ok(())
237    }
238}
239
240pub struct Quoted<'a, D: fmt::Display + 'a + ?Sized>(pub &'a D);
241
242impl<'a, D: fmt::Display + 'a + ?Sized> fmt::Display for Quoted<'a, D> {
243    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
244        let unquoted = format!("{}", self.0);
245        if unquoted.is_empty() {
246            // return Ok(());
247        }
248        let quoted = unquoted.replace('\\', r"\\").replace('"', r#"\""#);
249        formatter.write_fmt(format_args!("\"{}\"", &quoted))
250    }
251}
252
253// }}}