1use std::collections::BTreeMap;
2use std::fmt::Display;
3
4use indexmap::IndexMap;
5use serde::ser;
6use serde::{Serialize, Serializer};
7
8use crate::{Path, Root};
9
10pub trait Validate {
12 fn validate<P, R>(&self, _root: &Root, _path: P, _report: &mut R)
14 where
15 P: Fn() -> Path,
16 R: FnMut(&dyn Fn() -> Path, Error),
17 {
18 }
20}
21
22#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
24pub enum Error {
25 IndexNotFound,
27
28 Invalid,
30
31 Missing,
33
34 Oversize,
36
37 Unsupported,
39}
40
41#[derive(Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
43pub enum Checked<T> {
44 Valid(T),
46
47 Invalid,
49}
50
51impl<T> Display for Checked<T>
52where
53 T: Display,
54{
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 match self {
57 Checked::Valid(valid) => f.write_fmt(format_args!("Valid: {}", valid)),
58 Checked::Invalid => f.write_str("Invalid"),
59 }
60 }
61}
62
63impl<T> Checked<T> {
64 pub fn as_ref(&self) -> Checked<&T> {
66 match *self {
67 Checked::Valid(ref item) => Checked::Valid(item),
68 Checked::Invalid => Checked::Invalid,
69 }
70 }
71
72 pub fn unwrap(self) -> T {
78 match self {
79 Checked::Valid(item) => item,
80 Checked::Invalid => panic!("attempted to unwrap an invalid item"),
81 }
82 }
83}
84
85impl<T: Serialize> Serialize for Checked<T> {
86 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
87 where
88 S: Serializer,
89 {
90 match *self {
91 Checked::Valid(ref item) => item.serialize(serializer),
92 Checked::Invalid => Err(ser::Error::custom("invalid item")),
93 }
94 }
95}
96
97impl<T: Clone> Clone for Checked<T> {
98 fn clone(&self) -> Self {
99 match *self {
100 Checked::Valid(ref item) => Checked::Valid(item.clone()),
101 Checked::Invalid => Checked::Invalid,
102 }
103 }
104}
105
106impl<T: Copy> Copy for Checked<T> {}
107
108impl<T: Default> Default for Checked<T> {
109 fn default() -> Self {
110 Checked::Valid(T::default())
111 }
112}
113
114impl<T> Validate for Checked<T> {
115 fn validate<P, R>(&self, _root: &Root, path: P, report: &mut R)
116 where
117 P: Fn() -> Path,
118 R: FnMut(&dyn Fn() -> Path, Error),
119 {
120 match *self {
121 Checked::Valid(_) => {}
122 Checked::Invalid => report(&path, Error::Invalid),
123 }
124 }
125}
126
127#[derive(
129 Clone,
130 Copy,
131 Debug,
132 Default,
133 Eq,
134 Hash,
135 PartialEq,
136 serde_derive::Deserialize,
137 serde_derive::Serialize,
138)]
139pub struct USize64(pub u64);
140
141impl From<u64> for USize64 {
142 fn from(value: u64) -> Self {
143 Self(value)
144 }
145}
146
147impl From<usize> for USize64 {
148 fn from(value: usize) -> Self {
149 Self(value as u64)
150 }
151}
152
153impl Validate for USize64 {
154 fn validate<P, R>(&self, _root: &Root, path: P, report: &mut R)
155 where
156 P: Fn() -> Path,
157 R: FnMut(&dyn Fn() -> Path, Error),
158 {
159 if usize::try_from(self.0).is_err() {
160 report(&path, Error::Oversize);
161 }
162 }
163}
164
165impl<K: ToString + Validate, V: Validate> Validate for IndexMap<K, V> {
166 fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
167 where
168 P: Fn() -> Path,
169 R: FnMut(&dyn Fn() -> Path, Error),
170 {
171 for (key, value) in self.iter() {
172 key.validate(root, || path().key(&key.to_string()), report);
173 value.validate(root, || path().key(&key.to_string()), report);
174 }
175 }
176}
177
178impl<K: ToString + Validate, V: Validate> Validate for BTreeMap<K, V> {
179 fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
180 where
181 P: Fn() -> Path,
182 R: FnMut(&dyn Fn() -> Path, Error),
183 {
184 for (key, value) in self.iter() {
185 key.validate(root, || path().key(&key.to_string()), report);
186 value.validate(root, || path().key(&key.to_string()), report);
187 }
188 }
189}
190
191impl Validate for serde_json::Map<String, serde_json::Value> {
192 fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
193 where
194 P: Fn() -> Path,
195 R: FnMut(&dyn Fn() -> Path, Error),
196 {
197 for (key, value) in self.iter() {
198 key.validate(root, || path().key(&key.to_string()), report);
199 value.validate(root, || path().key(&key.to_string()), report);
200 }
201 }
202}
203
204impl<T: Validate> Validate for Option<T> {
205 fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
206 where
207 P: Fn() -> Path,
208 R: FnMut(&dyn Fn() -> Path, Error),
209 {
210 if let Some(value) = self.as_ref() {
211 value.validate(root, path, report);
212 }
213 }
214}
215
216impl<T: Validate> Validate for Vec<T> {
217 fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
218 where
219 P: Fn() -> Path,
220 R: FnMut(&dyn Fn() -> Path, Error),
221 {
222 for (index, value) in self.iter().enumerate() {
223 value.validate(root, || path().index(index), report);
224 }
225 }
226}
227
228impl std::error::Error for Error {}
238
239impl std::fmt::Display for Error {
240 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
241 write!(
242 f,
243 "{}",
244 match *self {
245 Error::IndexNotFound => "Index not found",
246 Error::Invalid => "Invalid value",
247 Error::Missing => "Missing data",
248 Error::Oversize => "Size exceeds system limits",
249 Error::Unsupported => "Unsupported extension",
250 }
251 )
252 }
253}
254
255impl Validate for bool {}
256impl Validate for u32 {}
257impl Validate for i32 {}
258impl Validate for f32 {}
259impl Validate for () {}
260impl Validate for String {}
261impl Validate for serde_json::Value {}
262impl<T: Validate, const N: usize> Validate for [T; N] {}