use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("Authentication failed: {message} (HTTP {status_code})")]
Authentication {
message: String,
status_code: u16,
},
#[error("Validation error: {message} (HTTP {status_code})")]
Validation {
message: String,
status_code: u16,
},
#[error("Rate limit exceeded: {message} (HTTP {status_code})")]
RateLimit {
message: String,
status_code: u16,
},
#[error("HTTP request failed: {0}")]
Request(#[from] reqwest::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("API error: {message} (HTTP {status_code})")]
Api {
message: String,
status_code: u16,
},
#[error("Invalid configuration: {0}")]
InvalidConfig(String),
#[error("Builder validation error: {0}")]
BuilderValidation(String),
}
impl Error {
pub fn status_code(&self) -> Option<u16> {
match self {
Error::Authentication { status_code, .. }
| Error::Validation { status_code, .. }
| Error::RateLimit { status_code, .. }
| Error::Api { status_code, .. } => Some(*status_code),
_ => None,
}
}
pub fn is_authentication_error(&self) -> bool {
matches!(self, Error::Authentication { .. })
}
pub fn is_validation_error(&self) -> bool {
matches!(self, Error::Validation { .. })
}
pub fn is_rate_limit_error(&self) -> bool {
matches!(self, Error::RateLimit { .. })
}
pub fn is_retryable(&self) -> bool {
match self {
Error::RateLimit { .. } => true,
Error::Api { status_code, .. } => *status_code >= 500,
Error::Request(e) => {
e.is_connect() || e.is_timeout()
}
_ => false,
}
}
}