librespot_core/
error.rs

1use std::{
2    error, fmt,
3    num::{ParseIntError, TryFromIntError},
4    str::Utf8Error,
5    string::FromUtf8Error,
6};
7
8use base64::DecodeError;
9use http::{
10    header::{InvalidHeaderName, InvalidHeaderValue, ToStrError},
11    method::InvalidMethod,
12    status::InvalidStatusCode,
13    uri::{InvalidUri, InvalidUriParts},
14};
15use protobuf::Error as ProtobufError;
16use thiserror::Error;
17use tokio::sync::{
18    mpsc::error::SendError, oneshot::error::RecvError, AcquireError, TryAcquireError,
19};
20use url::ParseError;
21
22use librespot_oauth::OAuthError;
23
24#[derive(Debug)]
25pub struct Error {
26    pub kind: ErrorKind,
27    pub error: Box<dyn error::Error + Send + Sync>,
28}
29
30#[derive(Clone, Copy, Debug, Eq, Error, Hash, Ord, PartialEq, PartialOrd)]
31pub enum ErrorKind {
32    #[error("The operation was cancelled by the caller")]
33    Cancelled = 1,
34
35    #[error("Unknown error")]
36    Unknown = 2,
37
38    #[error("Client specified an invalid argument")]
39    InvalidArgument = 3,
40
41    #[error("Deadline expired before operation could complete")]
42    DeadlineExceeded = 4,
43
44    #[error("Requested entity was not found")]
45    NotFound = 5,
46
47    #[error("Attempt to create entity that already exists")]
48    AlreadyExists = 6,
49
50    #[error("Permission denied")]
51    PermissionDenied = 7,
52
53    #[error("No valid authentication credentials")]
54    Unauthenticated = 16,
55
56    #[error("Resource has been exhausted")]
57    ResourceExhausted = 8,
58
59    #[error("Invalid state")]
60    FailedPrecondition = 9,
61
62    #[error("Operation aborted")]
63    Aborted = 10,
64
65    #[error("Operation attempted past the valid range")]
66    OutOfRange = 11,
67
68    #[error("Not implemented")]
69    Unimplemented = 12,
70
71    #[error("Internal error")]
72    Internal = 13,
73
74    #[error("Service unavailable")]
75    Unavailable = 14,
76
77    #[error("Unrecoverable data loss or corruption")]
78    DataLoss = 15,
79
80    #[error("Operation must not be used")]
81    DoNotUse = -1,
82}
83
84#[derive(Debug, Error)]
85struct ErrorMessage(String);
86
87impl fmt::Display for ErrorMessage {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        write!(f, "{}", self.0)
90    }
91}
92
93impl Error {
94    pub fn new<E>(kind: ErrorKind, error: E) -> Error
95    where
96        E: Into<Box<dyn error::Error + Send + Sync>>,
97    {
98        Self {
99            kind,
100            error: error.into(),
101        }
102    }
103
104    pub fn aborted<E>(error: E) -> Error
105    where
106        E: Into<Box<dyn error::Error + Send + Sync>>,
107    {
108        Self {
109            kind: ErrorKind::Aborted,
110            error: error.into(),
111        }
112    }
113
114    pub fn already_exists<E>(error: E) -> Error
115    where
116        E: Into<Box<dyn error::Error + Send + Sync>>,
117    {
118        Self {
119            kind: ErrorKind::AlreadyExists,
120            error: error.into(),
121        }
122    }
123
124    pub fn cancelled<E>(error: E) -> Error
125    where
126        E: Into<Box<dyn error::Error + Send + Sync>>,
127    {
128        Self {
129            kind: ErrorKind::Cancelled,
130            error: error.into(),
131        }
132    }
133
134    pub fn data_loss<E>(error: E) -> Error
135    where
136        E: Into<Box<dyn error::Error + Send + Sync>>,
137    {
138        Self {
139            kind: ErrorKind::DataLoss,
140            error: error.into(),
141        }
142    }
143
144    pub fn deadline_exceeded<E>(error: E) -> Error
145    where
146        E: Into<Box<dyn error::Error + Send + Sync>>,
147    {
148        Self {
149            kind: ErrorKind::DeadlineExceeded,
150            error: error.into(),
151        }
152    }
153
154    pub fn do_not_use<E>(error: E) -> Error
155    where
156        E: Into<Box<dyn error::Error + Send + Sync>>,
157    {
158        Self {
159            kind: ErrorKind::DoNotUse,
160            error: error.into(),
161        }
162    }
163
164    pub fn failed_precondition<E>(error: E) -> Error
165    where
166        E: Into<Box<dyn error::Error + Send + Sync>>,
167    {
168        Self {
169            kind: ErrorKind::FailedPrecondition,
170            error: error.into(),
171        }
172    }
173
174    pub fn internal<E>(error: E) -> Error
175    where
176        E: Into<Box<dyn error::Error + Send + Sync>>,
177    {
178        Self {
179            kind: ErrorKind::Internal,
180            error: error.into(),
181        }
182    }
183
184    pub fn invalid_argument<E>(error: E) -> Error
185    where
186        E: Into<Box<dyn error::Error + Send + Sync>>,
187    {
188        Self {
189            kind: ErrorKind::InvalidArgument,
190            error: error.into(),
191        }
192    }
193
194    pub fn not_found<E>(error: E) -> Error
195    where
196        E: Into<Box<dyn error::Error + Send + Sync>>,
197    {
198        Self {
199            kind: ErrorKind::NotFound,
200            error: error.into(),
201        }
202    }
203
204    pub fn out_of_range<E>(error: E) -> Error
205    where
206        E: Into<Box<dyn error::Error + Send + Sync>>,
207    {
208        Self {
209            kind: ErrorKind::OutOfRange,
210            error: error.into(),
211        }
212    }
213
214    pub fn permission_denied<E>(error: E) -> Error
215    where
216        E: Into<Box<dyn error::Error + Send + Sync>>,
217    {
218        Self {
219            kind: ErrorKind::PermissionDenied,
220            error: error.into(),
221        }
222    }
223
224    pub fn resource_exhausted<E>(error: E) -> Error
225    where
226        E: Into<Box<dyn error::Error + Send + Sync>>,
227    {
228        Self {
229            kind: ErrorKind::ResourceExhausted,
230            error: error.into(),
231        }
232    }
233
234    pub fn unauthenticated<E>(error: E) -> Error
235    where
236        E: Into<Box<dyn error::Error + Send + Sync>>,
237    {
238        Self {
239            kind: ErrorKind::Unauthenticated,
240            error: error.into(),
241        }
242    }
243
244    pub fn unavailable<E>(error: E) -> Error
245    where
246        E: Into<Box<dyn error::Error + Send + Sync>>,
247    {
248        Self {
249            kind: ErrorKind::Unavailable,
250            error: error.into(),
251        }
252    }
253
254    pub fn unimplemented<E>(error: E) -> Error
255    where
256        E: Into<Box<dyn error::Error + Send + Sync>>,
257    {
258        Self {
259            kind: ErrorKind::Unimplemented,
260            error: error.into(),
261        }
262    }
263
264    pub fn unknown<E>(error: E) -> Error
265    where
266        E: Into<Box<dyn error::Error + Send + Sync>>,
267    {
268        Self {
269            kind: ErrorKind::Unknown,
270            error: error.into(),
271        }
272    }
273}
274
275impl std::error::Error for Error {
276    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
277        self.error.source()
278    }
279}
280
281impl fmt::Display for Error {
282    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
283        write!(fmt, "{} {{ ", self.kind)?;
284        self.error.fmt(fmt)?;
285        write!(fmt, " }}")
286    }
287}
288
289impl From<OAuthError> for Error {
290    fn from(err: OAuthError) -> Self {
291        use OAuthError::*;
292        match err {
293            AuthCodeBadUri { .. }
294            | AuthCodeNotFound { .. }
295            | AuthCodeListenerRead
296            | AuthCodeListenerParse => Error::unavailable(err),
297            AuthCodeStdinRead
298            | AuthCodeListenerBind { .. }
299            | AuthCodeListenerTerminated
300            | AuthCodeListenerWrite
301            | Recv
302            | ExchangeCode { .. } => Error::internal(err),
303            _ => Error::failed_precondition(err),
304        }
305    }
306}
307
308impl From<DecodeError> for Error {
309    fn from(err: DecodeError) -> Self {
310        Self::new(ErrorKind::FailedPrecondition, err)
311    }
312}
313
314impl From<http::Error> for Error {
315    fn from(err: http::Error) -> Self {
316        if err.is::<InvalidHeaderName>()
317            || err.is::<InvalidHeaderValue>()
318            || err.is::<InvalidMethod>()
319            || err.is::<InvalidUri>()
320            || err.is::<InvalidUriParts>()
321        {
322            return Self::new(ErrorKind::InvalidArgument, err);
323        }
324
325        if err.is::<InvalidStatusCode>() {
326            return Self::new(ErrorKind::FailedPrecondition, err);
327        }
328
329        Self::new(ErrorKind::Unknown, err)
330    }
331}
332
333impl From<hyper::Error> for Error {
334    fn from(err: hyper::Error) -> Self {
335        if err.is_parse() || err.is_parse_status() || err.is_user() {
336            return Self::new(ErrorKind::Internal, err);
337        }
338
339        if err.is_canceled() {
340            return Self::new(ErrorKind::Cancelled, err);
341        }
342
343        if err.is_incomplete_message() {
344            return Self::new(ErrorKind::DataLoss, err);
345        }
346
347        if err.is_body_write_aborted() || err.is_closed() {
348            return Self::new(ErrorKind::Aborted, err);
349        }
350
351        if err.is_timeout() {
352            return Self::new(ErrorKind::DeadlineExceeded, err);
353        }
354
355        Self::new(ErrorKind::Unknown, err)
356    }
357}
358
359impl From<hyper_util::client::legacy::Error> for Error {
360    fn from(err: hyper_util::client::legacy::Error) -> Self {
361        if err.is_connect() {
362            return Self::new(ErrorKind::Unavailable, err);
363        }
364
365        Self::new(ErrorKind::Unknown, err)
366    }
367}
368
369impl From<time::error::Parse> for Error {
370    fn from(err: time::error::Parse) -> Self {
371        Self::new(ErrorKind::FailedPrecondition, err)
372    }
373}
374
375impl From<quick_xml::Error> for Error {
376    fn from(err: quick_xml::Error) -> Self {
377        Self::new(ErrorKind::FailedPrecondition, err)
378    }
379}
380
381impl From<serde_json::Error> for Error {
382    fn from(err: serde_json::Error) -> Self {
383        Self::new(ErrorKind::FailedPrecondition, err)
384    }
385}
386
387impl From<std::io::Error> for Error {
388    fn from(err: std::io::Error) -> Self {
389        use std::io::ErrorKind as IoErrorKind;
390        match err.kind() {
391            IoErrorKind::NotFound => Self::new(ErrorKind::NotFound, err),
392            IoErrorKind::PermissionDenied => Self::new(ErrorKind::PermissionDenied, err),
393            IoErrorKind::AddrInUse | IoErrorKind::AlreadyExists => {
394                Self::new(ErrorKind::AlreadyExists, err)
395            }
396            IoErrorKind::AddrNotAvailable
397            | IoErrorKind::ConnectionRefused
398            | IoErrorKind::NotConnected => Self::new(ErrorKind::Unavailable, err),
399            IoErrorKind::BrokenPipe
400            | IoErrorKind::ConnectionReset
401            | IoErrorKind::ConnectionAborted => Self::new(ErrorKind::Aborted, err),
402            IoErrorKind::Interrupted | IoErrorKind::WouldBlock => {
403                Self::new(ErrorKind::Cancelled, err)
404            }
405            IoErrorKind::InvalidData | IoErrorKind::UnexpectedEof => {
406                Self::new(ErrorKind::FailedPrecondition, err)
407            }
408            IoErrorKind::TimedOut => Self::new(ErrorKind::DeadlineExceeded, err),
409            IoErrorKind::InvalidInput => Self::new(ErrorKind::InvalidArgument, err),
410            IoErrorKind::WriteZero => Self::new(ErrorKind::ResourceExhausted, err),
411            _ => Self::new(ErrorKind::Unknown, err),
412        }
413    }
414}
415
416impl From<FromUtf8Error> for Error {
417    fn from(err: FromUtf8Error) -> Self {
418        Self::new(ErrorKind::FailedPrecondition, err)
419    }
420}
421
422impl From<InvalidHeaderValue> for Error {
423    fn from(err: InvalidHeaderValue) -> Self {
424        Self::new(ErrorKind::InvalidArgument, err)
425    }
426}
427
428impl From<InvalidUri> for Error {
429    fn from(err: InvalidUri) -> Self {
430        Self::new(ErrorKind::InvalidArgument, err)
431    }
432}
433
434impl From<ParseError> for Error {
435    fn from(err: ParseError) -> Self {
436        Self::new(ErrorKind::FailedPrecondition, err)
437    }
438}
439
440impl From<ParseIntError> for Error {
441    fn from(err: ParseIntError) -> Self {
442        Self::new(ErrorKind::FailedPrecondition, err)
443    }
444}
445
446impl From<TryFromIntError> for Error {
447    fn from(err: TryFromIntError) -> Self {
448        Self::new(ErrorKind::FailedPrecondition, err)
449    }
450}
451
452impl From<ProtobufError> for Error {
453    fn from(err: ProtobufError) -> Self {
454        Self::new(ErrorKind::FailedPrecondition, err)
455    }
456}
457
458impl From<RecvError> for Error {
459    fn from(err: RecvError) -> Self {
460        Self::new(ErrorKind::Internal, err)
461    }
462}
463
464impl<T> From<SendError<T>> for Error {
465    fn from(err: SendError<T>) -> Self {
466        Self {
467            kind: ErrorKind::Internal,
468            error: ErrorMessage(err.to_string()).into(),
469        }
470    }
471}
472
473impl From<AcquireError> for Error {
474    fn from(err: AcquireError) -> Self {
475        Self {
476            kind: ErrorKind::ResourceExhausted,
477            error: ErrorMessage(err.to_string()).into(),
478        }
479    }
480}
481
482impl From<TryAcquireError> for Error {
483    fn from(err: TryAcquireError) -> Self {
484        Self {
485            kind: ErrorKind::ResourceExhausted,
486            error: ErrorMessage(err.to_string()).into(),
487        }
488    }
489}
490
491impl From<ToStrError> for Error {
492    fn from(err: ToStrError) -> Self {
493        Self::new(ErrorKind::FailedPrecondition, err)
494    }
495}
496
497impl From<Utf8Error> for Error {
498    fn from(err: Utf8Error) -> Self {
499        Self::new(ErrorKind::FailedPrecondition, err)
500    }
501}