1use std::fmt::{self, Display, Formatter};
2
3#[derive(Clone, Debug, Eq, PartialEq)]
4pub enum Error {
5 InvalidConfiguration(String),
6 MissingCredentials,
7 Transport(String),
8 Timeout(String),
9 RateLimited {
10 retry_after: Option<u64>,
11 body: Option<String>,
12 },
13 HttpStatus {
14 status: u16,
15 body: Option<String>,
16 },
17 Deserialize(String),
18 InvalidRequest(String),
19 Pagination(String),
20 NotImplemented {
21 operation: &'static str,
22 },
23}
24
25impl Display for Error {
26 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
27 match self {
28 Self::InvalidConfiguration(message) => {
29 write!(f, "invalid configuration: {message}")
30 }
31 Self::MissingCredentials => write!(f, "missing credentials"),
32 Self::Transport(message) => write!(f, "transport error: {message}"),
33 Self::Timeout(message) => write!(f, "timeout error: {message}"),
34 Self::RateLimited { retry_after, body } => match (retry_after, body) {
35 (Some(value), Some(body)) => {
36 write!(f, "rate limited, retry_after={value}, body={body}")
37 }
38 (Some(value), None) => write!(f, "rate limited, retry_after={value}"),
39 (None, Some(body)) => write!(f, "rate limited, body={body}"),
40 (None, None) => write!(f, "rate limited"),
41 },
42 Self::HttpStatus { status, body } => match body {
43 Some(body) => write!(f, "http status error: {status}, body={body}"),
44 None => write!(f, "http status error: {status}"),
45 },
46 Self::Deserialize(message) => write!(f, "deserialize error: {message}"),
47 Self::InvalidRequest(message) => write!(f, "invalid request: {message}"),
48 Self::Pagination(message) => write!(f, "pagination error: {message}"),
49 Self::NotImplemented { operation } => {
50 write!(f, "operation not implemented: {operation}")
51 }
52 }
53 }
54}
55
56impl std::error::Error for Error {}
57
58impl Error {
59 pub(crate) fn from_reqwest(error: reqwest::Error) -> Self {
60 if error.is_timeout() {
61 Self::Timeout(error.to_string())
62 } else {
63 Self::Transport(error.to_string())
64 }
65 }
66}