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}