1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum MuxiError {
5 #[error("Authentication error ({code}): {message}")]
6 Authentication { code: String, message: String, status: u16 },
7
8 #[error("Authorization error ({code}): {message}")]
9 Authorization { code: String, message: String, status: u16 },
10
11 #[error("Not found ({code}): {message}")]
12 NotFound { code: String, message: String, status: u16 },
13
14 #[error("Conflict ({code}): {message}")]
15 Conflict { code: String, message: String, status: u16 },
16
17 #[error("Validation error ({code}): {message}")]
18 Validation { code: String, message: String, status: u16 },
19
20 #[error("Rate limited: {message} (retry after {retry_after:?}s)")]
21 RateLimit { message: String, status: u16, retry_after: Option<u32> },
22
23 #[error("Server error ({code}): {message}")]
24 Server { code: String, message: String, status: u16 },
25
26 #[error("Connection error: {0}")]
27 Connection(String),
28
29 #[error("Request error: {0}")]
30 Request(#[from] reqwest::Error),
31
32 #[error("JSON error: {0}")]
33 Json(#[from] serde_json::Error),
34
35 #[error("Unknown error ({code}): {message}")]
36 Unknown { code: String, message: String, status: u16 },
37}
38
39impl MuxiError {
40 pub fn from_response(status: u16, code: Option<String>, message: String, retry_after: Option<u32>) -> Self {
41 let code = code.unwrap_or_default();
42 match status {
43 401 => MuxiError::Authentication { code: if code.is_empty() { "UNAUTHORIZED".to_string() } else { code }, message, status },
44 403 => MuxiError::Authorization { code: if code.is_empty() { "FORBIDDEN".to_string() } else { code }, message, status },
45 404 => MuxiError::NotFound { code: if code.is_empty() { "NOT_FOUND".to_string() } else { code }, message, status },
46 409 => MuxiError::Conflict { code: if code.is_empty() { "CONFLICT".to_string() } else { code }, message, status },
47 422 => MuxiError::Validation { code: if code.is_empty() { "VALIDATION_ERROR".to_string() } else { code }, message, status },
48 429 => MuxiError::RateLimit { message, status, retry_after },
49 500..=504 => MuxiError::Server { code: if code.is_empty() { "SERVER_ERROR".to_string() } else { code }, message, status },
50 _ => MuxiError::Unknown { code: if code.is_empty() { "ERROR".to_string() } else { code }, message, status },
51 }
52 }
53}
54
55pub type Result<T> = std::result::Result<T, MuxiError>;