use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("API error {status}: {message}")]
Api {
status: u16,
message: String,
code: Option<String>,
},
#[error("HTTP request failed: {0}")]
Http(#[from] reqwest::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("Environment variable error: {0}")]
Env(#[from] std::env::VarError),
#[error("Configuration error: {0}")]
Config(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
impl Error {
pub fn api(status: u16, message: impl Into<String>) -> Self {
Self::Api {
status,
message: message.into(),
code: None,
}
}
pub fn api_with_code(status: u16, message: impl Into<String>, code: impl Into<String>) -> Self {
Self::Api {
status,
message: message.into(),
code: Some(code.into()),
}
}
pub fn config(message: impl Into<String>) -> Self {
Self::Config(message.into())
}
pub fn is_not_found(&self) -> bool {
matches!(self, Self::Api { status: 404, .. })
}
pub fn is_unauthorized(&self) -> bool {
matches!(self, Self::Api { status: 401, .. })
}
pub fn is_forbidden(&self) -> bool {
matches!(self, Self::Api { status: 403, .. })
}
pub fn is_conflict(&self) -> bool {
matches!(self, Self::Api { status: 409, .. })
}
pub fn is_rate_limited(&self) -> bool {
matches!(self, Self::Api { status: 429, .. })
}
pub fn is_server_error(&self) -> bool {
matches!(self, Self::Api { status, .. } if *status >= 500 && *status < 600)
}
}
pub type Result<T> = std::result::Result<T, Error>;