armature_validation/
errors.rs

1// Validation errors
2
3use std::fmt;
4
5/// Validation error for a single field
6#[derive(Debug, Clone)]
7pub struct ValidationError {
8    /// Field name that failed validation
9    pub field: String,
10
11    /// Error message
12    pub message: String,
13
14    /// Validation constraint that failed
15    pub constraint: String,
16
17    /// Value that failed validation (optional)
18    pub value: Option<String>,
19}
20
21impl ValidationError {
22    /// Create a new validation error
23    pub fn new(field: impl Into<String>, message: impl Into<String>) -> Self {
24        let field = field.into();
25        Self {
26            constraint: "custom".to_string(),
27            message: message.into(),
28            field,
29            value: None,
30        }
31    }
32
33    /// Set the constraint name
34    pub fn with_constraint(mut self, constraint: impl Into<String>) -> Self {
35        self.constraint = constraint.into();
36        self
37    }
38
39    /// Set the invalid value
40    pub fn with_value(mut self, value: impl Into<String>) -> Self {
41        self.value = Some(value.into());
42        self
43    }
44}
45
46impl fmt::Display for ValidationError {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        write!(f, "{}: {}", self.field, self.message)
49    }
50}
51
52impl std::error::Error for ValidationError {}
53
54/// Collection of validation errors
55#[derive(Debug, Clone)]
56pub struct ValidationErrors {
57    pub errors: Vec<ValidationError>,
58}
59
60impl ValidationErrors {
61    /// Create a new validation errors collection
62    pub fn new(errors: Vec<ValidationError>) -> Self {
63        Self { errors }
64    }
65
66    /// Check if there are any errors
67    pub fn is_empty(&self) -> bool {
68        self.errors.is_empty()
69    }
70
71    /// Get the number of errors
72    pub fn len(&self) -> usize {
73        self.errors.len()
74    }
75
76    /// Add an error
77    pub fn add(&mut self, error: ValidationError) {
78        self.errors.push(error);
79    }
80
81    /// Get errors for a specific field
82    pub fn get_field_errors(&self, field: &str) -> Vec<&ValidationError> {
83        self.errors.iter().filter(|e| e.field == field).collect()
84    }
85
86    /// Convert to JSON representation
87    pub fn to_json(&self) -> serde_json::Value {
88        serde_json::json!({
89            "errors": self.errors.iter().map(|e| {
90                serde_json::json!({
91                    "field": e.field,
92                    "message": e.message,
93                    "constraint": e.constraint,
94                    "value": e.value,
95                })
96            }).collect::<Vec<_>>()
97        })
98    }
99}
100
101impl fmt::Display for ValidationErrors {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        for error in &self.errors {
104            writeln!(f, "{}", error)?;
105        }
106        Ok(())
107    }
108}
109
110impl std::error::Error for ValidationErrors {}
111
112impl From<Vec<ValidationError>> for ValidationErrors {
113    fn from(errors: Vec<ValidationError>) -> Self {
114        Self::new(errors)
115    }
116}