#[derive(Debug, Clone)]
pub struct ValidationError {
pub path: String,
pub severity: Severity,
pub rule_id: String,
pub message: String,
}
impl ValidationError {
pub fn new(
path: impl Into<String>,
severity: Severity,
rule_id: impl Into<String>,
message: impl Into<String>,
) -> Self {
Self {
path: path.into(),
severity,
rule_id: rule_id.into(),
message: message.into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Severity {
Error,
Warning,
Info,
}
#[derive(Debug, Clone)]
pub struct ValidationResult {
pub errors: Vec<ValidationError>,
}
impl ValidationResult {
pub fn new(errors: Vec<ValidationError>) -> Self {
Self { errors }
}
pub fn is_valid(&self) -> bool {
!self.errors.iter().any(|e| e.severity == Severity::Error)
}
pub fn error_count(&self) -> usize {
self.errors
.iter()
.filter(|e| e.severity == Severity::Error)
.count()
}
pub fn warning_count(&self) -> usize {
self.errors
.iter()
.filter(|e| e.severity == Severity::Warning)
.count()
}
pub fn merge(&mut self, other: ValidationResult) {
self.errors.extend(other.errors);
}
}
impl Default for ValidationResult {
fn default() -> Self {
Self::new(vec![])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_valid_with_no_errors() {
let result = ValidationResult::new(vec![]);
assert!(result.is_valid());
}
#[test]
fn is_invalid_with_error() {
let result = ValidationResult::new(vec![ValidationError::new(
"/path",
Severity::Error,
"RULE_1",
"Some error",
)]);
assert!(!result.is_valid());
}
#[test]
fn is_valid_with_only_warning() {
let result = ValidationResult::new(vec![ValidationError::new(
"/path",
Severity::Warning,
"RULE_1",
"Some warning",
)]);
assert!(result.is_valid());
assert_eq!(result.warning_count(), 1);
assert_eq!(result.error_count(), 0);
}
#[test]
fn counts_are_correct() {
let result = ValidationResult::new(vec![
ValidationError::new("/a", Severity::Error, "R1", "e1"),
ValidationError::new("/b", Severity::Error, "R2", "e2"),
ValidationError::new("/c", Severity::Warning, "R3", "w1"),
ValidationError::new("/d", Severity::Info, "R4", "i1"),
]);
assert_eq!(result.error_count(), 2);
assert_eq!(result.warning_count(), 1);
assert!(!result.is_valid());
}
#[test]
fn merge_combines_findings() {
let mut a = ValidationResult::new(vec![ValidationError::new(
"/a",
Severity::Error,
"R1",
"e1",
)]);
let b = ValidationResult::new(vec![ValidationError::new(
"/b",
Severity::Warning,
"R2",
"w1",
)]);
a.merge(b);
assert_eq!(a.errors.len(), 2);
assert_eq!(a.error_count(), 1);
assert_eq!(a.warning_count(), 1);
}
}