mx20022_validate/
error.rs1#[derive(Debug, Clone)]
5pub struct ValidationError {
6 pub path: String,
8 pub severity: Severity,
10 pub rule_id: String,
12 pub message: String,
14}
15
16impl ValidationError {
17 pub fn new(
28 path: impl Into<String>,
29 severity: Severity,
30 rule_id: impl Into<String>,
31 message: impl Into<String>,
32 ) -> Self {
33 Self {
34 path: path.into(),
35 severity,
36 rule_id: rule_id.into(),
37 message: message.into(),
38 }
39 }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum Severity {
45 Error,
47 Warning,
49 Info,
51}
52
53#[derive(Debug, Clone)]
66pub struct ValidationResult {
67 pub errors: Vec<ValidationError>,
69}
70
71impl ValidationResult {
72 pub fn new(errors: Vec<ValidationError>) -> Self {
74 Self { errors }
75 }
76
77 pub fn is_valid(&self) -> bool {
79 !self.errors.iter().any(|e| e.severity == Severity::Error)
80 }
81
82 pub fn error_count(&self) -> usize {
84 self.errors
85 .iter()
86 .filter(|e| e.severity == Severity::Error)
87 .count()
88 }
89
90 pub fn warning_count(&self) -> usize {
92 self.errors
93 .iter()
94 .filter(|e| e.severity == Severity::Warning)
95 .count()
96 }
97
98 pub fn merge(&mut self, other: ValidationResult) {
100 self.errors.extend(other.errors);
101 }
102}
103
104impl Default for ValidationResult {
105 fn default() -> Self {
106 Self::new(vec![])
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn is_valid_with_no_errors() {
116 let result = ValidationResult::new(vec![]);
117 assert!(result.is_valid());
118 }
119
120 #[test]
121 fn is_invalid_with_error() {
122 let result = ValidationResult::new(vec![ValidationError::new(
123 "/path",
124 Severity::Error,
125 "RULE_1",
126 "Some error",
127 )]);
128 assert!(!result.is_valid());
129 }
130
131 #[test]
132 fn is_valid_with_only_warning() {
133 let result = ValidationResult::new(vec![ValidationError::new(
134 "/path",
135 Severity::Warning,
136 "RULE_1",
137 "Some warning",
138 )]);
139 assert!(result.is_valid());
140 assert_eq!(result.warning_count(), 1);
141 assert_eq!(result.error_count(), 0);
142 }
143
144 #[test]
145 fn counts_are_correct() {
146 let result = ValidationResult::new(vec![
147 ValidationError::new("/a", Severity::Error, "R1", "e1"),
148 ValidationError::new("/b", Severity::Error, "R2", "e2"),
149 ValidationError::new("/c", Severity::Warning, "R3", "w1"),
150 ValidationError::new("/d", Severity::Info, "R4", "i1"),
151 ]);
152 assert_eq!(result.error_count(), 2);
153 assert_eq!(result.warning_count(), 1);
154 assert!(!result.is_valid());
155 }
156
157 #[test]
158 fn merge_combines_findings() {
159 let mut a = ValidationResult::new(vec![ValidationError::new(
160 "/a",
161 Severity::Error,
162 "R1",
163 "e1",
164 )]);
165 let b = ValidationResult::new(vec![ValidationError::new(
166 "/b",
167 Severity::Warning,
168 "R2",
169 "w1",
170 )]);
171 a.merge(b);
172 assert_eq!(a.errors.len(), 2);
173 assert_eq!(a.error_count(), 1);
174 assert_eq!(a.warning_count(), 1);
175 }
176}