Skip to main content

lastfm_rs/
error.rs

1//! Last.fm Error Handling
2//!
3//! This module handles any and all errors related to Last.fm, such as when
4//! authentication fails, the provided API key is invalid, and various other
5//! errors. Please check the [LastFMErrorResponse] struct for more information
6//! about the various types of errors the Last.fm API transmits when the API encounters
7//! an error.
8//!
9//! [LastFMErrorResponse]: crate::error::LastFMErrorResponse
10
11use serde::Deserialize;
12use std::error::Error as StdError;
13use std::fmt::{Display, Formatter, Result as FmtResult};
14
15/// Kinds of errors that could happen at runtime.
16#[derive(Debug)]
17pub enum Error {
18    /// An error occurred while parsing the received JSON
19    ParsingError(serde_json::error::Error),
20    /// An error occurred while a request was being made to the API.
21    HTTPError(reqwest::Error),
22    /// An error returned by the Last.fm API.
23    LastFMError(LastFMErrorResponse),
24}
25
26impl StdError for Error {
27    fn source(&self) -> Option<&(dyn StdError + 'static)> {
28        match *self {
29            Error::ParsingError(ref e) => Some(e),
30            Error::HTTPError(ref e) => Some(e),
31            Error::LastFMError(_) => None,
32        }
33    }
34}
35
36impl Display for Error {
37    fn fmt(&self, f: &mut Formatter) -> FmtResult {
38        match *self {
39            Error::ParsingError(ref inner) => inner.fmt(f),
40            Error::HTTPError(ref inner) => inner.fmt(f),
41            Error::LastFMError(ref inner) => inner.fmt(f),
42        }
43    }
44}
45
46/// Representation of all the errors exposed by the Last.fm API.
47#[derive(Debug)]
48pub enum LastFMErrorResponse {
49    /// Invalid Service - This service does not exist.
50    InvalidService(LastFMError),
51    /// Invalid Method - No method exists by the name provided.
52    InvalidMethod(LastFMError),
53    /// Authentication Failed - Failed to authenticate with the Last.fm API.
54    AuthenticationFailed(LastFMError),
55    /// Invalid Format - Service does not exist in the format given.
56    InvalidFormat(LastFMError),
57    /// Invalid Parameters - A required parameter is missing from the request,
58    /// or one or more parameters are invalid.
59    InvalidParameters(LastFMError),
60    /// Invalid Resource Specified - An invalid resource was specified.
61    InvalidResourceSpecified(LastFMError),
62    /// Operation Failed - Something else went wrong.
63    OperationFailed(LastFMError),
64    /// Invalid Session Key - Please re-authenticate with the Last.fm API.
65    InvalidSessionKey(LastFMError),
66    /// Invalid API Key - An invalid API key was provided.
67    InvalidAPIKey(LastFMError),
68    /// Service Offline - The given service is temporarily offline. Try again later.
69    ServiceOffline(LastFMError),
70    /// Invalid Method Signature Supplied - An invalid signature for the given methoid was supplied.
71    InvalidMethodSignatureSupplied(LastFMError),
72    /// Generic Error - An unknown error has occurred.
73    GenericError(LastFMError),
74    /// Suspended API Key - The given API key has been suspended.
75    SuspendedAPIKey(LastFMError),
76    /// Rate Limit Exceeded - The rate limit for this API key has been exceeded.
77    RateLimitExceeded(LastFMError),
78}
79
80impl Display for LastFMErrorResponse {
81    fn fmt(&self, f: &mut Formatter) -> FmtResult {
82        match *self {
83            LastFMErrorResponse::InvalidService(ref inner) => write!(f, "{}", inner.message),
84            LastFMErrorResponse::InvalidMethod(ref inner) => write!(f, "{}", inner.message),
85            LastFMErrorResponse::AuthenticationFailed(ref inner) => write!(f, "{}", inner.message),
86            LastFMErrorResponse::InvalidFormat(ref inner) => write!(f, "{}", inner.message),
87            LastFMErrorResponse::InvalidParameters(ref inner) => write!(f, "{}", inner.message),
88            LastFMErrorResponse::InvalidResourceSpecified(ref inner) => write!(f, "{}", inner.message),
89            LastFMErrorResponse::OperationFailed(ref inner) => write!(f, "{}", inner.message),
90            LastFMErrorResponse::InvalidSessionKey(ref inner) => write!(f, "{}", inner.message),
91            LastFMErrorResponse::InvalidAPIKey(ref inner) => write!(f, "{}", inner.message),
92            LastFMErrorResponse::ServiceOffline(ref inner) => write!(f, "{}", inner.message),
93            LastFMErrorResponse::InvalidMethodSignatureSupplied(ref inner) => write!(f, "{}", inner.message),
94            LastFMErrorResponse::GenericError(ref inner) => write!(f, "{}", inner.message),
95            LastFMErrorResponse::SuspendedAPIKey(ref inner) => write!(f, "{}", inner.message),
96            LastFMErrorResponse::RateLimitExceeded(ref inner) => write!(f, "{}", inner.message),
97        }
98    }
99}
100
101/// A generic Last.fm response when the request can't be accomplished.
102#[derive(Deserialize, Debug)]
103pub struct LastFMError {
104    /// The error code associated with the error.
105    pub error: i32,
106    /// The message associated with the error.
107    pub message: String,
108    /// Any links associated with the error, if available.
109    pub links: Option<Vec<String>>,
110}
111
112impl From<LastFMError> for LastFMErrorResponse {
113    fn from(lastm_error: LastFMError) -> LastFMErrorResponse {
114        match lastm_error.error {
115            2 => LastFMErrorResponse::InvalidService(lastm_error),
116            3 => LastFMErrorResponse::InvalidMethod(lastm_error),
117            4 => LastFMErrorResponse::AuthenticationFailed(lastm_error),
118            5 => LastFMErrorResponse::InvalidFormat(lastm_error),
119            6 => LastFMErrorResponse::InvalidParameters(lastm_error),
120            7 => LastFMErrorResponse::InvalidResourceSpecified(lastm_error),
121            8 => LastFMErrorResponse::OperationFailed(lastm_error),
122            9 => LastFMErrorResponse::InvalidSessionKey(lastm_error),
123            10 => LastFMErrorResponse::InvalidAPIKey(lastm_error),
124            11 => LastFMErrorResponse::ServiceOffline(lastm_error),
125            13 => LastFMErrorResponse::InvalidMethodSignatureSupplied(lastm_error),
126            16 => LastFMErrorResponse::GenericError(lastm_error),
127            26 => LastFMErrorResponse::SuspendedAPIKey(lastm_error),
128            29 => LastFMErrorResponse::RateLimitExceeded(lastm_error),
129            _ => LastFMErrorResponse::GenericError(lastm_error),
130        }
131    }
132}