1use crate::error::{VldError, format_value_short};
4
5#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
9pub struct FieldResult {
10 pub name: String,
12 pub input: serde_json::Value,
14 pub result: Result<serde_json::Value, VldError>,
17}
18
19impl FieldResult {
20 pub fn is_ok(&self) -> bool {
22 self.result.is_ok()
23 }
24
25 pub fn is_err(&self) -> bool {
27 self.result.is_err()
28 }
29}
30
31impl std::fmt::Display for FieldResult {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 match &self.result {
34 Ok(v) => write!(f, "✔ {}: {}", self.name, format_value_short(v)),
35 Err(e) => {
36 let received = format_value_short(&self.input);
37 for (i, issue) in e.issues.iter().enumerate() {
38 if i > 0 {
39 writeln!(f)?;
40 }
41 write!(
42 f,
43 "✖ {}: {} (received: {})",
44 self.name, issue.message, received
45 )?;
46 }
47 Ok(())
48 }
49 }
50 }
51}
52
53#[derive(Debug)]
64pub struct ParseResult<T> {
65 pub value: T,
67 field_results: Vec<FieldResult>,
69}
70
71impl<T> ParseResult<T> {
72 pub fn new(value: T, field_results: Vec<FieldResult>) -> Self {
74 Self {
75 value,
76 field_results,
77 }
78 }
79
80 pub fn fields(&self) -> &[FieldResult] {
82 &self.field_results
83 }
84
85 pub fn field(&self, name: &str) -> Option<&FieldResult> {
89 self.field_results.iter().find(|f| f.name == name)
90 }
91
92 pub fn valid_fields(&self) -> Vec<&FieldResult> {
94 self.field_results.iter().filter(|f| f.is_ok()).collect()
95 }
96
97 pub fn error_fields(&self) -> Vec<&FieldResult> {
99 self.field_results.iter().filter(|f| f.is_err()).collect()
100 }
101
102 pub fn is_valid(&self) -> bool {
104 self.field_results.iter().all(|f| f.is_ok())
105 }
106
107 pub fn has_errors(&self) -> bool {
109 self.field_results.iter().any(|f| f.is_err())
110 }
111
112 pub fn valid_count(&self) -> usize {
114 self.field_results.iter().filter(|f| f.is_ok()).count()
115 }
116
117 pub fn error_count(&self) -> usize {
119 self.field_results.iter().filter(|f| f.is_err()).count()
120 }
121
122 pub fn into_value(self) -> T {
124 self.value
125 }
126
127 pub fn into_parts(self) -> (T, Vec<FieldResult>) {
129 (self.value, self.field_results)
130 }
131}
132
133impl<T: serde::Serialize> ParseResult<T> {
134 pub fn save_to_file(&self, path: &std::path::Path) -> std::io::Result<()> {
136 let json = serde_json::to_string_pretty(&self.value)
137 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
138 if let Some(parent) = path.parent() {
139 if !parent.as_os_str().is_empty() {
140 std::fs::create_dir_all(parent)?;
141 }
142 }
143 std::fs::write(path, json)
144 }
145
146 pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
148 serde_json::to_string_pretty(&self.value)
149 }
150
151 pub fn to_json_value(&self) -> Result<serde_json::Value, serde_json::Error> {
153 serde_json::to_value(&self.value)
154 }
155}
156
157impl<T: std::fmt::Debug> std::fmt::Display for ParseResult<T> {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 writeln!(
160 f,
161 "ParseResult ({} valid, {} errors):",
162 self.valid_count(),
163 self.error_count()
164 )?;
165 for field in &self.field_results {
166 writeln!(f, " {}", field)?;
167 }
168 Ok(())
169 }
170}