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