askr/validation/
result.rs1use 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 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, rules_checked: results.len(),
138 rules_passed,
139 input_length: value.len(),
140 attempts: None,
141 },
142 validation_results: results,
143 }
144 }
145}