use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorResponse {
pub error: ErrorDetail,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorDetail {
pub message: String,
pub r#type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub param: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
}
impl ErrorResponse {
pub fn new(message: impl Into<String>, error_type: impl Into<String>) -> Self {
Self {
error: ErrorDetail {
message: message.into(),
r#type: error_type.into(),
param: None,
code: None,
},
}
}
pub fn invalid_request(message: impl Into<String>) -> Self {
Self::new(message, "invalid_request_error")
}
pub fn authentication_error() -> Self {
Self::new("Invalid authentication", "authentication_error")
}
pub fn rate_limit_error() -> Self {
Self::new("Rate limit exceeded", "rate_limit_error")
}
pub fn server_error(message: impl Into<String>) -> Self {
Self::new(message, "server_error")
}
}
pub fn normalize_error(status: u16, message: impl Into<String>) -> ErrorResponse {
let message = message.into();
match status {
400 => ErrorResponse::invalid_request(message),
401 => ErrorResponse::authentication_error(),
429 => ErrorResponse::rate_limit_error(),
_ => ErrorResponse::server_error(message),
}
}
impl std::fmt::Display for ErrorResponse {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.error.r#type, self.error.message)
}
}
impl std::error::Error for ErrorResponse {}