1use thiserror::Error;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[repr(i32)]
16pub enum ErrorCode {
17 Success = 200,
19 ParamError = 400,
21 NoPermission = 401,
23 TokenExpired = 402,
25 ServerError = 500,
27 RateLimit = 501,
29}
30
31impl ErrorCode {
32 pub fn from_code(code: i32) -> Option<ErrorCode> {
34 match code {
35 200 => Some(ErrorCode::Success),
36 400 => Some(ErrorCode::ParamError),
37 401 => Some(ErrorCode::NoPermission),
38 402 => Some(ErrorCode::TokenExpired),
39 500 => Some(ErrorCode::ServerError),
40 501 => Some(ErrorCode::RateLimit),
41 _ => None,
42 }
43 }
44}
45
46#[derive(Error, Debug)]
48pub enum Error {
49 #[error("API error {code}: {message}")]
51 Api {
52 code: i32,
54 message: String,
56 },
57
58 #[error("authentication error: {reason}")]
60 Auth {
61 reason: String,
63 },
64
65 #[error("network error: {0}")]
67 Network(#[from] reqwest::Error),
68
69 #[error("validation error on field '{field}': {message}")]
71 Validation {
72 field: String,
74 message: String,
76 },
77
78 #[error("parse error: {err}, raw response: {raw_response}")]
80 Parse {
81 raw_response: String,
83 err: String,
85 },
86}
87
88impl Error {
89 pub fn api(code: i32, message: impl Into<String>) -> Self {
91 Error::Api {
92 code,
93 message: message.into(),
94 }
95 }
96
97 pub fn auth(reason: impl Into<String>) -> Self {
99 Error::Auth {
100 reason: reason.into(),
101 }
102 }
103
104 pub fn validation(field: impl Into<String>, message: impl Into<String>) -> Self {
106 Error::Validation {
107 field: field.into(),
108 message: message.into(),
109 }
110 }
111
112 pub fn parse(raw_response: impl Into<String>, err: impl Into<String>) -> Self {
114 Error::Parse {
115 raw_response: raw_response.into(),
116 err: err.into(),
117 }
118 }
119
120 pub fn is_token_expired(&self) -> bool {
122 matches!(self, Error::Api { code, .. } if *code == ErrorCode::TokenExpired as i32)
123 }
124
125 pub fn error_code(&self) -> Option<ErrorCode> {
127 if let Error::Api { code, .. } = self {
128 ErrorCode::from_code(*code)
129 } else {
130 None
131 }
132 }
133}
134
135pub type Result<T> = std::result::Result<T, Error>;