use std::fmt;
#[derive(Debug)]
pub enum TranslationError {
NetworkError(reqwest::Error),
HttpError {
status: reqwest::StatusCode,
body: String,
},
AuthenticationError(String),
TimeoutError,
MaxRetriesExceeded {
attempts: u32,
errors: Vec<TranslationError>, },
ServiceError(String),
ConfigurationError(String),
Other(String),
}
impl TranslationError {
pub fn is_retryable(&self) -> bool {
match self {
TranslationError::NetworkError(_) => true,
TranslationError::HttpError { status, .. } => {
status.is_server_error()
}
TranslationError::TimeoutError => true,
_ => false,
}
}
}
impl fmt::Display for TranslationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TranslationError::NetworkError(e) => write!(f, "Network error: {}", e),
TranslationError::HttpError { status, body } => {
write!(f, "HTTP error {}: {}", status, body)
}
TranslationError::AuthenticationError(msg) => {
write!(f, "Authentication error: {}", msg)
}
TranslationError::TimeoutError => write!(f, "Request timeout"),
TranslationError::MaxRetriesExceeded { attempts, errors } => {
writeln!(f, "Max retries exceeded after {} attempts", attempts)?;
for (i, error) in errors.iter().enumerate() {
writeln!(f, " Attempt {}: {}", i + 1, error)?;
}
Ok(())
}
TranslationError::ServiceError(msg) => write!(f, "Service error: {}", msg),
TranslationError::ConfigurationError(msg) => write!(f, "Configuration error: {}", msg),
TranslationError::Other(msg) => write!(f, "Error: {}", msg),
}
}
}
impl std::error::Error for TranslationError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
TranslationError::NetworkError(e) => Some(e),
TranslationError::MaxRetriesExceeded { .. } => None,
_ => None,
}
}
}
impl From<reqwest::Error> for TranslationError {
fn from(error: reqwest::Error) -> Self {
if error.is_timeout() {
TranslationError::TimeoutError
} else if error.is_connect() {
TranslationError::NetworkError(error)
} else {
TranslationError::NetworkError(error)
}
}
}
impl From<serde_json::Error> for TranslationError {
fn from(error: serde_json::Error) -> Self {
TranslationError::ServiceError(format!("JSON parsing error: {}", error))
}
}
impl From<anyhow::Error> for TranslationError {
fn from(error: anyhow::Error) -> Self {
TranslationError::Other(error.to_string())
}
}