use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorResponse {
pub status: u16,
pub error: String,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub trace_id: Option<String>,
pub timestamp: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ValidationErrorDetail {
pub field: String,
pub message: String,
pub code: String,
}
impl ValidationErrorDetail {
pub fn new(
field: impl Into<String>,
message: impl Into<String>,
code: impl Into<String>,
) -> Self {
Self {
field: field.into(),
message: message.into(),
code: code.into(),
}
}
pub fn required(field: impl Into<String>) -> Self {
let field = field.into();
Self {
field: field.clone(),
message: format!("{} is required", field),
code: "REQUIRED".to_string(),
}
}
pub fn invalid_format(field: impl Into<String>, expected: &str) -> Self {
let field = field.into();
Self {
field: field.clone(),
message: format!("{} has invalid format, expected: {}", field, expected),
code: "INVALID_FORMAT".to_string(),
}
}
pub fn invalid_length(field: impl Into<String>, min: usize, max: usize) -> Self {
let field = field.into();
Self {
field: field.clone(),
message: format!("{} length must be between {} and {}", field, min, max),
code: "INVALID_LENGTH".to_string(),
}
}
pub fn min_value(field: impl Into<String>, min: impl std::fmt::Display) -> Self {
let field = field.into();
Self {
field: field.clone(),
message: format!("{} must be at least {}", field, min),
code: "MIN_VALUE".to_string(),
}
}
pub fn max_value(field: impl Into<String>, max: impl std::fmt::Display) -> Self {
let field = field.into();
Self {
field: field.clone(),
message: format!("{} must be at most {}", field, max),
code: "MAX_VALUE".to_string(),
}
}
}