mpd/
error.rs

1//! This module defines different errors occurring during communication with MPD.
2//!
3//! There're following kinds of possible errors:
4//!
5//!   - IO errors (due to network communication failures),
6//!   - parsing errors (because of bugs in parsing server response),
7//!   - protocol errors (happen when we get unexpected data from server,
8//!     mostly because protocol version mismatch, network data corruption
9//!     or just bugs in the client),
10//!   - server errors (run-time errors coming from MPD due to some MPD
11//!     errors, like database failures or sound problems)
12//!
13//! This module defines all necessary infrastructure to represent these kinds or errors.
14
15use std::convert::From;
16use std::error::Error as StdError;
17use std::fmt;
18use std::io::Error as IoError;
19use std::num::{ParseFloatError, ParseIntError};
20use std::result;
21use std::str::FromStr;
22use std::string::ParseError as StringParseError;
23
24// Server errors {{{
25/// Server error codes, as defined in [libmpdclient](http://www.musicpd.org/doc/libmpdclient/protocol_8h_source.html)
26#[cfg_attr(feature = "serde", derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr))]
27#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
28#[repr(u8)]
29pub enum ErrorCode {
30    /// not a list
31    NotList = 1,
32    /// bad command arguments
33    Argument = 2,
34    /// invalid password
35    Password = 3,
36    /// insufficient permissions
37    Permission = 4,
38    /// unknown command
39    UnknownCmd = 5,
40    /// object doesn't exist
41    NoExist = 50,
42    /// maximum playlist size exceeded
43    PlaylistMax = 51,
44    /// general system error
45    System = 52,
46    /// error loading playlist
47    PlaylistLoad = 53,
48    /// update database is already in progress
49    UpdateAlready = 54,
50    /// player synchronization error
51    PlayerSync = 55,
52    /// object already exists
53    Exist = 56,
54}
55
56impl FromStr for ErrorCode {
57    type Err = ParseError;
58    fn from_str(s: &str) -> result::Result<ErrorCode, ParseError> {
59        use self::ErrorCode::*;
60        match s.parse()? {
61            1 => Ok(NotList),
62            2 => Ok(Argument),
63            3 => Ok(Password),
64            4 => Ok(Permission),
65            5 => Ok(UnknownCmd),
66
67            50 => Ok(NoExist),
68            51 => Ok(PlaylistMax),
69            52 => Ok(System),
70            53 => Ok(PlaylistLoad),
71            54 => Ok(UpdateAlready),
72            55 => Ok(PlayerSync),
73            56 => Ok(Exist),
74
75            v => Err(ParseError::BadErrorCode(v)),
76        }
77    }
78}
79
80impl StdError for ErrorCode {}
81
82impl fmt::Display for ErrorCode {
83    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84        use self::ErrorCode::*;
85
86        let desc = match *self {
87            NotList => "not a list",
88            Argument => "invalid argument",
89            Password => "invalid password",
90            Permission => "permission",
91            UnknownCmd => "unknown command",
92
93            NoExist => "item not found",
94            PlaylistMax => "playlist overflow",
95            System => "system",
96            PlaylistLoad => "playload load",
97            UpdateAlready => "already updating",
98            PlayerSync => "player syncing",
99            Exist => "already exists",
100        };
101
102        f.write_str(desc)
103    }
104}
105
106/// Server error
107#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
108#[derive(Debug, Clone, PartialEq)]
109pub struct ServerError {
110    /// server error code
111    pub code: ErrorCode,
112    /// command position in command list
113    pub pos: u16,
114    /// command name, which caused the error
115    pub command: String,
116    /// detailed error description
117    pub detail: String,
118}
119
120impl StdError for ServerError {}
121
122impl fmt::Display for ServerError {
123    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124        write!(f, "{} error (`{}') at {}", self.code, self.detail, self.pos)
125    }
126}
127
128impl FromStr for ServerError {
129    type Err = ParseError;
130    fn from_str(s: &str) -> result::Result<ServerError, ParseError> {
131        // ACK [<code>@<index>] {<command>} <description>
132        if let Some(s) = s.strip_prefix("ACK [") {
133            if let (Some(atsign), Some(right_bracket)) = (s.find('@'), s.find(']')) {
134                match (s[..atsign].parse(), s[atsign + 1..right_bracket].parse()) {
135                    (Ok(code), Ok(pos)) => {
136                        let s = &s[right_bracket + 1..];
137                        if let (Some(left_brace), Some(right_brace)) = (s.find('{'), s.find('}')) {
138                            let command = s[left_brace + 1..right_brace].to_string();
139                            let detail = s[right_brace + 1..].trim().to_string();
140                            Ok(ServerError { code, pos, command, detail })
141                        } else {
142                            Err(ParseError::NoMessage)
143                        }
144                    }
145                    (Err(_), _) => Err(ParseError::BadCode),
146                    (_, Err(_)) => Err(ParseError::BadPos),
147                }
148            } else {
149                Err(ParseError::NoCodePos)
150            }
151        } else {
152            Err(ParseError::NotAck)
153        }
154    }
155}
156// }}}
157
158// Error {{{
159/// Main error type, describing all possible error classes for the crate
160#[derive(Debug)]
161pub enum Error {
162    /// IO errors (low-level network communication failures)
163    Io(IoError),
164    /// parsing errors (unknown data came from server)
165    Parse(ParseError),
166    /// protocol errors (e.g. missing required fields in server response, no handshake message etc.)
167    Proto(ProtoError),
168    /// server errors (a.k.a. `ACK` responses from server)
169    Server(ServerError),
170}
171
172/// Shortcut type for MPD results
173pub type Result<T> = result::Result<T, Error>;
174
175impl StdError for Error {
176    fn source(&self) -> Option<&(dyn StdError + 'static)> {
177        match *self {
178            Error::Io(ref err) => Some(err),
179            Error::Parse(ref err) => Some(err),
180            Error::Proto(ref err) => Some(err),
181            Error::Server(ref err) => Some(err),
182        }
183    }
184}
185
186impl fmt::Display for Error {
187    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188        match *self {
189            Error::Io(ref err) => err.fmt(f),
190            Error::Parse(ref err) => err.fmt(f),
191            Error::Proto(ref err) => err.fmt(f),
192            Error::Server(ref err) => err.fmt(f),
193        }
194    }
195}
196
197impl From<IoError> for Error {
198    fn from(e: IoError) -> Error {
199        Error::Io(e)
200    }
201}
202impl From<ParseError> for Error {
203    fn from(e: ParseError) -> Error {
204        Error::Parse(e)
205    }
206}
207impl From<ProtoError> for Error {
208    fn from(e: ProtoError) -> Error {
209        Error::Proto(e)
210    }
211}
212impl From<ParseIntError> for Error {
213    fn from(e: ParseIntError) -> Error {
214        Error::Parse(ParseError::BadInteger(e))
215    }
216}
217impl From<ParseFloatError> for Error {
218    fn from(e: ParseFloatError) -> Error {
219        Error::Parse(ParseError::BadFloat(e))
220    }
221}
222impl From<ServerError> for Error {
223    fn from(e: ServerError) -> Error {
224        Error::Server(e)
225    }
226}
227
228// }}}
229
230// Parse errors {{{
231/// Parsing error kinds
232#[derive(Debug, Clone, PartialEq)]
233pub enum ParseError {
234    /// invalid integer
235    BadInteger(ParseIntError),
236    /// invalid float
237    BadFloat(ParseFloatError),
238    /// some other invalid value
239    BadValue(String),
240    /// invalid version format (should be x.y.z)
241    BadVersion,
242    /// the response is not an `ACK` (not an error)
243    /// (this is not actually an error, just a marker
244    /// to try to parse the response as some other type,
245    /// like a pair)
246    NotAck,
247    /// invalid pair
248    BadPair,
249    /// invalid error code in `ACK` response
250    BadCode,
251    /// invalid command position in `ACK` response
252    BadPos,
253    /// missing command position and/or error code in `ACK` response
254    NoCodePos,
255    /// missing error message in `ACK` response
256    NoMessage,
257    /// missing bitrate in audio format field
258    NoRate,
259    /// missing bits in audio format field
260    NoBits,
261    /// missing channels in audio format field
262    NoChans,
263    /// invalid bitrate in audio format field
264    BadRate(ParseIntError),
265    /// invalid bits in audio format field
266    BadBits(ParseIntError),
267    /// invalid channels in audio format field
268    BadChans(ParseIntError),
269    /// unknown state in state status field
270    BadState(String),
271    /// unknown error code in `ACK` response
272    BadErrorCode(usize),
273}
274
275impl StdError for ParseError {}
276
277impl fmt::Display for ParseError {
278    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
279        use self::ParseError::*;
280
281        let desc = match *self {
282            BadInteger(_) => "invalid integer",
283            BadFloat(_) => "invalid float",
284            BadValue(_) => "invalid value",
285            BadVersion => "invalid version",
286            NotAck => "not an ACK",
287            BadPair => "invalid pair",
288            BadCode => "invalid code",
289            BadPos => "invalid position",
290            NoCodePos => "missing code and position",
291            NoMessage => "missing position",
292            NoRate => "missing audio format rate",
293            NoBits => "missing audio format bits",
294            NoChans => "missing audio format channels",
295            BadRate(_) => "invalid audio format rate",
296            BadBits(_) => "invalid audio format bits",
297            BadChans(_) => "invalid audio format channels",
298            BadState(_) => "invalid playing state",
299            BadErrorCode(_) => "unknown error code",
300        };
301
302        write!(f, "{}", desc)
303    }
304}
305
306impl From<ParseIntError> for ParseError {
307    fn from(e: ParseIntError) -> ParseError {
308        ParseError::BadInteger(e)
309    }
310}
311
312impl From<ParseFloatError> for ParseError {
313    fn from(e: ParseFloatError) -> ParseError {
314        ParseError::BadFloat(e)
315    }
316}
317
318impl From<StringParseError> for ParseError {
319    fn from(e: StringParseError) -> ParseError {
320        match e {}
321    }
322}
323// }}}
324
325// Protocol errors {{{
326/// Protocol errors
327///
328/// They usually occur when server violate expected command response format,
329/// like missing fields in answer to some command, missing closing `OK`
330/// line after data stream etc.
331#[derive(Debug, Clone, PartialEq)]
332pub enum ProtoError {
333    /// `OK` was expected, but it was missing
334    NotOk,
335    /// a data pair was expected
336    NotPair,
337    /// invalid handshake banner received
338    BadBanner,
339    /// expected some field, but it was missing
340    NoField(&'static str),
341    /// expected sticker value, but didn't find it
342    BadSticker,
343}
344
345impl StdError for ProtoError {}
346
347impl fmt::Display for ProtoError {
348    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
349        let desc = match *self {
350            ProtoError::NotOk => "OK expected",
351            ProtoError::NotPair => "pair expected",
352            ProtoError::BadBanner => "banner error",
353            ProtoError::NoField(_) => "missing field",
354            ProtoError::BadSticker => "sticker error",
355        };
356
357        write!(f, "{}", desc)
358    }
359}
360// }}}