use reqwest::Error as ReqwestError;
use serde_json::Error as SerdeJsonError;
use std::fmt;
#[derive(Debug)]
pub enum ClientError {
Http(ReqwestError),
Json(SerdeJsonError),
InvalidUrl(String),
Authentication(String),
ApiError { status: u16, message: String },
InvalidFilter(String),
Timeout,
Other(String),
}
impl fmt::Display for ClientError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ClientError::Http(err) => write!(f, "HTTP request failed: {}", err),
ClientError::Json(err) => write!(f, "JSON parsing failed: {}", err),
ClientError::InvalidUrl(url) => write!(f, "Invalid URL: {}", url),
ClientError::Authentication(msg) => write!(f, "Authentication failed: {}", msg),
ClientError::ApiError { status, message } => {
write!(f, "API error (status {}): {}", status, message)
}
ClientError::InvalidFilter(msg) => write!(f, "Invalid filter: {}", msg),
ClientError::Timeout => write!(f, "Request timed out"),
ClientError::Other(msg) => write!(f, "Client error: {}", msg),
}
}
}
impl std::error::Error for ClientError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ClientError::Http(err) => Some(err),
ClientError::Json(err) => Some(err),
_ => None,
}
}
}
impl From<ReqwestError> for ClientError {
fn from(err: ReqwestError) -> ClientError {
if err.is_timeout() {
ClientError::Timeout
} else if err.is_status() {
if let Some(status) = err.status() {
ClientError::ApiError {
status: status.as_u16(),
message: err.to_string(),
}
} else {
ClientError::Http(err)
}
} else {
ClientError::Http(err)
}
}
}
impl From<SerdeJsonError> for ClientError {
fn from(err: SerdeJsonError) -> ClientError {
ClientError::Json(err)
}
}
impl From<url::ParseError> for ClientError {
fn from(err: url::ParseError) -> ClientError {
ClientError::InvalidUrl(err.to_string())
}
}
pub type Result<T> = std::result::Result<T, ClientError>;