glowmarkt/
error.rs

1//! A basic error container.
2
3use std::fmt::{self, Display};
4
5use reqwest::StatusCode;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8/// The type of an error.
9pub enum ErrorKind {
10    /// The requested item was not found.
11    NotFound,
12    /// Authentication failed.
13    NotAuthenticated,
14    /// A network error.
15    Network,
16    /// An error likely caused by this crate.
17    Client,
18    /// An error on the server.
19    Server,
20    /// An error decoding the API response.
21    Response,
22}
23
24/// A fairly generic error container.
25pub struct Error {
26    /// The type of this error.
27    pub kind: ErrorKind,
28    /// A description of this error.
29    pub message: String,
30}
31
32pub(crate) fn maybe<T>(result: Result<T, Error>) -> Result<Option<T>, Error> {
33    match result {
34        Ok(val) => Ok(Some(val)),
35        Err(e) => {
36            if e.kind == ErrorKind::NotFound {
37                Ok(None)
38            } else {
39                Err(e)
40            }
41        }
42    }
43}
44
45impl Display for Error {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        f.pad(&format!("{:?}: {}", self.kind, self.message))
48    }
49}
50
51impl From<Error> for String {
52    fn from(error: Error) -> String {
53        format!("{}", error)
54    }
55}
56
57impl From<reqwest::Error> for Error {
58    fn from(error: reqwest::Error) -> Self {
59        let kind = if let Some(status) = error.status() {
60            if status == StatusCode::NOT_FOUND {
61                ErrorKind::NotFound
62            } else if status == StatusCode::UNAUTHORIZED {
63                ErrorKind::NotAuthenticated
64            } else if status.is_server_error() {
65                ErrorKind::Server
66            } else {
67                ErrorKind::Client
68            }
69        } else {
70            ErrorKind::Network
71        };
72
73        Self {
74            kind,
75            message: error.to_string(),
76        }
77    }
78}
79
80impl From<serde_json::Error> for Error {
81    fn from(error: serde_json::Error) -> Self {
82        Self {
83            kind: ErrorKind::Response,
84            message: error.to_string(),
85        }
86    }
87}