Skip to main content

askr/validation/
result.rs

1use super::Priority;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct ValidationResult {
7    pub rule_name: String,
8    pub passed: bool,
9    pub priority: Priority,
10    pub message: Option<String>,
11    pub metadata: HashMap<String, serde_json::Value>,
12}
13
14impl ValidationResult {
15    pub fn success(rule_name: impl Into<String>) -> Self {
16        Self {
17            rule_name: rule_name.into(),
18            passed: true,
19            priority: Priority::Medium,
20            message: None,
21            metadata: HashMap::new(),
22        }
23    }
24
25    pub fn success_with_priority(rule_name: impl Into<String>, priority: Priority) -> Self {
26        Self {
27            rule_name: rule_name.into(),
28            passed: true,
29            priority,
30            message: None,
31            metadata: HashMap::new(),
32        }
33    }
34
35    pub fn failure(
36        rule_name: impl Into<String>,
37        priority: Priority,
38        message: impl Into<String>,
39    ) -> Self {
40        Self {
41            rule_name: rule_name.into(),
42            passed: false,
43            priority,
44            message: Some(message.into()),
45            metadata: HashMap::new(),
46        }
47    }
48
49    pub fn with_metadata(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
50        self.metadata.insert(key.into(), value);
51        self
52    }
53}
54
55#[derive(Debug, Clone)]
56pub struct PartialValidationResult {
57    pub first_error_pos: Option<usize>,
58    pub can_continue: bool,
59    pub suggestion: Option<String>,
60}
61
62impl PartialValidationResult {
63    pub fn valid() -> Self {
64        Self {
65            first_error_pos: None,
66            can_continue: true,
67            suggestion: None,
68        }
69    }
70
71    pub fn error_at(pos: usize) -> Self {
72        Self {
73            first_error_pos: Some(pos),
74            can_continue: true,
75            suggestion: None,
76        }
77    }
78
79    pub fn with_suggestion(mut self, suggestion: impl Into<String>) -> Self {
80        self.suggestion = Some(suggestion.into());
81        self
82    }
83
84    pub fn blocking(mut self) -> Self {
85        self.can_continue = false;
86        self
87    }
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct ValidationSummary {
92    pub value: String,
93    pub valid: bool,
94    pub error: Option<String>,
95    pub metadata: ValidationMetadata,
96    pub validation_results: Vec<ValidationResult>,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct ValidationMetadata {
101    pub validation_time_ms: u64,
102    pub rules_checked: usize,
103    pub rules_passed: usize,
104    pub input_length: usize,
105    pub attempts: Option<u32>,
106}
107
108impl ValidationSummary {
109    pub fn new(value: String, mut results: Vec<ValidationResult>) -> Self {
110        // Sort results by priority (Critical first)
111        results.sort_by(|a, b| {
112            a.priority
113                .cmp(&b.priority)
114                .then_with(|| a.rule_name.cmp(&b.rule_name))
115        });
116
117        let valid = results.iter().all(|r| r.passed);
118        let error = if valid {
119            None
120        } else {
121            results
122                .iter()
123                .filter(|r| !r.passed)
124                .min_by_key(|r| r.priority)
125                .and_then(|r| r.message.as_ref())
126                .cloned()
127        };
128
129        let rules_passed = results.iter().filter(|r| r.passed).count();
130
131        Self {
132            value: value.clone(),
133            valid,
134            error,
135            metadata: ValidationMetadata {
136                validation_time_ms: 0, // Will be set by validation engine
137                rules_checked: results.len(),
138                rules_passed,
139                input_length: value.len(),
140                attempts: None,
141            },
142            validation_results: results,
143        }
144    }
145}