systemprompt_traits/
validation_report.rs1use std::path::PathBuf;
7
8#[derive(Debug, Clone)]
10pub struct ValidationError {
11 pub field: String,
13
14 pub message: String,
16
17 pub path: Option<PathBuf>,
19
20 pub suggestion: Option<String>,
22}
23
24impl ValidationError {
25 #[must_use]
26 pub fn new(field: impl Into<String>, message: impl Into<String>) -> Self {
27 Self {
28 field: field.into(),
29 message: message.into(),
30 path: None,
31 suggestion: None,
32 }
33 }
34
35 #[must_use]
36 pub fn with_path(mut self, path: impl Into<PathBuf>) -> Self {
37 self.path = Some(path.into());
38 self
39 }
40
41 #[must_use]
42 pub fn with_suggestion(mut self, suggestion: impl Into<String>) -> Self {
43 self.suggestion = Some(suggestion.into());
44 self
45 }
46}
47
48impl std::fmt::Display for ValidationError {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 write!(f, "{}\n {}", self.field, self.message)?;
51 if let Some(ref path) = self.path {
52 write!(f, "\n Path: {}", path.display())?;
53 }
54 if let Some(ref suggestion) = self.suggestion {
55 write!(f, "\n To fix: {}", suggestion)?;
56 }
57 Ok(())
58 }
59}
60
61#[derive(Debug, Clone)]
63pub struct ValidationWarning {
64 pub field: String,
66
67 pub message: String,
69
70 pub suggestion: Option<String>,
72}
73
74impl ValidationWarning {
75 #[must_use]
76 pub fn new(field: impl Into<String>, message: impl Into<String>) -> Self {
77 Self {
78 field: field.into(),
79 message: message.into(),
80 suggestion: None,
81 }
82 }
83
84 #[must_use]
85 pub fn with_suggestion(mut self, suggestion: impl Into<String>) -> Self {
86 self.suggestion = Some(suggestion.into());
87 self
88 }
89}
90
91#[derive(Debug, Clone, Default)]
93pub struct ValidationReport {
94 pub domain: String,
96
97 pub errors: Vec<ValidationError>,
99
100 pub warnings: Vec<ValidationWarning>,
102}
103
104impl ValidationReport {
105 #[must_use]
106 pub fn new(domain: impl Into<String>) -> Self {
107 Self {
108 domain: domain.into(),
109 errors: Vec::new(),
110 warnings: Vec::new(),
111 }
112 }
113
114 pub fn add_error(&mut self, error: ValidationError) {
115 self.errors.push(error);
116 }
117
118 pub fn add_warning(&mut self, warning: ValidationWarning) {
119 self.warnings.push(warning);
120 }
121
122 pub fn has_errors(&self) -> bool {
123 !self.errors.is_empty()
124 }
125
126 pub fn has_warnings(&self) -> bool {
127 !self.warnings.is_empty()
128 }
129
130 pub fn is_clean(&self) -> bool {
131 self.errors.is_empty() && self.warnings.is_empty()
132 }
133
134 pub fn merge(&mut self, other: Self) {
136 self.errors.extend(other.errors);
137 self.warnings.extend(other.warnings);
138 }
139}
140
141#[derive(Debug, Clone, Default)]
143pub struct StartupValidationReport {
144 pub profile_path: Option<PathBuf>,
146
147 pub domains: Vec<ValidationReport>,
149
150 pub extensions: Vec<ValidationReport>,
152}
153
154impl StartupValidationReport {
155 #[must_use]
156 pub fn new() -> Self {
157 Self::default()
158 }
159
160 #[must_use]
161 pub fn with_profile_path(mut self, path: impl Into<PathBuf>) -> Self {
162 self.profile_path = Some(path.into());
163 self
164 }
165
166 pub fn add_domain(&mut self, report: ValidationReport) {
167 self.domains.push(report);
168 }
169
170 pub fn add_extension(&mut self, report: ValidationReport) {
171 self.extensions.push(report);
172 }
173
174 pub fn has_errors(&self) -> bool {
175 self.domains.iter().any(ValidationReport::has_errors)
176 || self.extensions.iter().any(ValidationReport::has_errors)
177 }
178
179 pub fn has_warnings(&self) -> bool {
180 self.domains.iter().any(ValidationReport::has_warnings)
181 || self.extensions.iter().any(ValidationReport::has_warnings)
182 }
183
184 pub fn error_count(&self) -> usize {
185 self.domains.iter().map(|r| r.errors.len()).sum::<usize>()
186 + self
187 .extensions
188 .iter()
189 .map(|r| r.errors.len())
190 .sum::<usize>()
191 }
192
193 pub fn warning_count(&self) -> usize {
194 self.domains.iter().map(|r| r.warnings.len()).sum::<usize>()
195 + self
196 .extensions
197 .iter()
198 .map(|r| r.warnings.len())
199 .sum::<usize>()
200 }
201}
202
203impl std::fmt::Display for StartupValidationReport {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 write!(
206 f,
207 "{} error(s), {} warning(s)",
208 self.error_count(),
209 self.warning_count()
210 )
211 }
212}
213
214#[derive(Debug, thiserror::Error)]
216#[error("Startup validation failed with {0}")]
217pub struct StartupValidationError(pub StartupValidationReport);
218
219impl From<StartupValidationReport> for StartupValidationError {
220 fn from(report: StartupValidationReport) -> Self {
221 Self(report)
222 }
223}