Skip to main content

context69_sdk/
error.rs

1use std::{error::Error as StdError, fmt, time::Duration};
2
3use reqwest::StatusCode;
4
5#[derive(Debug)]
6pub enum Error {
7    InvalidBaseUrl(String),
8    InvalidHeader(String),
9    Http(reqwest::Error),
10    Serialization(serde_json::Error),
11    HttpStatus {
12        status: StatusCode,
13        api_error: Option<String>,
14        body: String,
15    },
16    AuthenticationRequired,
17    RefreshFailed {
18        status: Option<StatusCode>,
19        message: String,
20    },
21    UrlJoin {
22        path: String,
23        source: url::ParseError,
24    },
25    InvalidTimeout(Duration),
26}
27
28impl fmt::Display for Error {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match self {
31            Self::InvalidBaseUrl(url) => write!(f, "invalid base url: {url}"),
32            Self::InvalidHeader(value) => write!(f, "invalid header value: {value}"),
33            Self::Http(error) => write!(f, "{error}"),
34            Self::Serialization(error) => write!(f, "{error}"),
35            Self::HttpStatus {
36                status,
37                api_error,
38                body,
39            } => {
40                if let Some(error) = api_error {
41                    write!(f, "http {status}: {error}")
42                } else {
43                    write!(f, "http {status}: {body}")
44                }
45            }
46            Self::AuthenticationRequired => {
47                write!(f, "authentication required before calling this API")
48            }
49            Self::RefreshFailed { status, message } => match status {
50                Some(status) => write!(f, "token refresh failed with {status}: {message}"),
51                None => write!(f, "token refresh failed: {message}"),
52            },
53            Self::UrlJoin { path, source } => {
54                write!(f, "failed to resolve path '{path}': {source}")
55            }
56            Self::InvalidTimeout(timeout) => {
57                write!(f, "invalid timeout: {:?}", timeout)
58            }
59        }
60    }
61}
62
63impl StdError for Error {
64    fn source(&self) -> Option<&(dyn StdError + 'static)> {
65        match self {
66            Self::Http(error) => Some(error),
67            Self::Serialization(error) => Some(error),
68            Self::UrlJoin { source, .. } => Some(source),
69            _ => None,
70        }
71    }
72}
73
74impl From<reqwest::Error> for Error {
75    fn from(value: reqwest::Error) -> Self {
76        Self::Http(value)
77    }
78}
79
80impl From<serde_json::Error> for Error {
81    fn from(value: serde_json::Error) -> Self {
82        Self::Serialization(value)
83    }
84}