1use std::fmt::{self, Display};
4
5use reqwest::StatusCode;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ErrorKind {
10 NotFound,
12 NotAuthenticated,
14 Network,
16 Client,
18 Server,
20 Response,
22}
23
24pub struct Error {
26 pub kind: ErrorKind,
28 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}