burn_central_client/
error.rs

1use reqwest::StatusCode;
2use serde::Deserialize;
3use std::fmt::{Display, Formatter};
4use thiserror::Error;
5
6#[derive(Clone, Debug, Deserialize, strum::Display)]
7#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
8#[non_exhaustive]
9pub enum ApiErrorCode {
10    ProjectAlreadyExists,
11    UnsupportedSdkVersion,
12    LimitReached,
13    // ...
14    #[serde(other)]
15    Unknown,
16}
17
18#[derive(Deserialize, Debug)]
19pub struct ApiErrorBody {
20    pub code: ApiErrorCode,
21    pub message: String,
22}
23
24impl Default for ApiErrorBody {
25    fn default() -> Self {
26        ApiErrorBody {
27            code: ApiErrorCode::Unknown,
28            message: "An unknown error occurred".to_string(),
29        }
30    }
31}
32
33impl Display for ApiErrorBody {
34    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35        write!(f, "{}: {}", self.code, self.message)
36    }
37}
38
39#[derive(Error, Debug)]
40pub enum ClientError {
41    #[error("Bad session id")]
42    BadSessionId,
43    #[error("Resource not found")]
44    NotFound,
45    #[error("Unauthorized access")]
46    Unauthorized,
47    #[error("Internal server error")]
48    InternalServerError,
49    #[error("Api error {status}: {body}")]
50    ApiError {
51        status: StatusCode,
52        body: ApiErrorBody,
53    },
54    #[error(transparent)]
55    Serialization(#[from] serde_json::Error),
56    #[error("Unknown Error: {0}")]
57    UnknownError(String),
58}
59
60impl ClientError {
61    pub fn is_not_found(&self) -> bool {
62        matches!(self, ClientError::NotFound)
63    }
64
65    pub fn code(&self) -> Option<ApiErrorCode> {
66        match self {
67            ClientError::ApiError { body, .. } => Some(body.code.clone()),
68            _ => None,
69        }
70    }
71
72    pub fn is_login_error(&self) -> bool {
73        matches!(self, ClientError::Unauthorized)
74    }
75}