1use crate::{Path, Root};
2use serde::ser;
3use serde::{Serialize, Serializer};
4use serde_json;
5use std;
6use std::collections::HashMap;
7use std::hash::{BuildHasher, Hash};
8
9pub trait Validate {
11 fn validate_minimally<P, R>(&self, _root: &Root, _path: P, _report: &mut R)
13 where
14 P: Fn() -> Path,
15 R: FnMut(&dyn Fn() -> Path, Error),
16 {
17 }
19
20 fn validate_completely<P, R>(&self, _root: &Root, _path: P, _report: &mut R)
26 where
27 P: Fn() -> Path,
28 R: FnMut(&dyn Fn() -> Path, Error),
29 {
30 }
32}
33
34#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub enum Error {
37 IndexOutOfBounds,
39
40 Invalid,
42
43 Missing,
45}
46
47#[derive(Debug, Eq, Hash, PartialEq)]
49pub enum Checked<T> {
50 Valid(T),
52
53 Invalid,
55}
56
57impl<T> Checked<T> {
58 pub fn as_ref(&self) -> Checked<&T> {
60 match *self {
61 Checked::Valid(ref item) => Checked::Valid(item),
62 Checked::Invalid => Checked::Invalid,
63 }
64 }
65
66 pub fn unwrap(self) -> T {
72 match self {
73 Checked::Valid(item) => item,
74 Checked::Invalid => panic!("attempted to unwrap an invalid item"),
75 }
76 }
77
78 pub fn is_valid(&self) -> bool {
80 match *self {
81 Checked::Valid(..) => true,
82 Checked::Invalid => false,
83 }
84 }
85}
86
87impl<T: Serialize> Serialize for Checked<T> {
88 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89 where
90 S: Serializer,
91 {
92 match *self {
93 Checked::Valid(ref item) => item.serialize(serializer),
94 Checked::Invalid => Err(ser::Error::custom("invalid item")),
95 }
96 }
97}
98
99impl<T: Clone> Clone for Checked<T> {
100 fn clone(&self) -> Self {
101 match *self {
102 Checked::Valid(ref item) => Checked::Valid(item.clone()),
103 Checked::Invalid => Checked::Invalid,
104 }
105 }
106}
107
108impl<T: Copy> Copy for Checked<T> {}
109
110impl<T: Default> Default for Checked<T> {
111 fn default() -> Self {
112 Checked::Valid(T::default())
113 }
114}
115
116impl<T> Validate for Checked<T> {
117 fn validate_minimally<P, R>(&self, _root: &Root, path: P, report: &mut R)
118 where
119 P: Fn() -> Path,
120 R: FnMut(&dyn Fn() -> Path, Error),
121 {
122 match *self {
123 Checked::Valid(_) => {}
124 Checked::Invalid => report(&path, Error::Invalid),
125 }
126 }
127}
128
129impl<K: Eq + Hash + ToString + Validate, V: Validate, H: BuildHasher> Validate for HashMap<K, V, H> {
130 fn validate_minimally<P, R>(&self, root: &Root, path: P, report: &mut R)
131 where
132 P: Fn() -> Path,
133 R: FnMut(&dyn Fn() -> Path, Error),
134 {
135 for (key, value) in self.iter() {
136 key.validate_minimally(root, || path().key(&key.to_string()), report);
137 value.validate_minimally(root, || path().key(&key.to_string()), report);
138 }
139 }
140
141 fn validate_completely<P, R>(&self, root: &Root, path: P, report: &mut R)
142 where
143 P: Fn() -> Path,
144 R: FnMut(&dyn Fn() -> Path, Error),
145 {
146 for (key, value) in self.iter() {
147 key.validate_completely(root, || path().key(&key.to_string()), report);
148 value.validate_completely(root, || path().key(&key.to_string()), report);
149 }
150 }
151}
152
153impl<T: Validate> Validate for Option<T> {
154 fn validate_minimally<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 let Some(value) = self.as_ref() {
160 value.validate_minimally(root, path, report);
161 }
162 }
163
164 fn validate_completely<P, R>(&self, root: &Root, path: P, report: &mut R)
165 where
166 P: Fn() -> Path,
167 R: FnMut(&dyn Fn() -> Path, Error),
168 {
169 if let Some(value) = self.as_ref() {
170 value.validate_completely(root, path, report);
171 }
172 }
173}
174
175impl<T: Validate> Validate for Vec<T> {
176 fn validate_minimally<P, R>(&self, root: &Root, path: P, report: &mut R)
177 where
178 P: Fn() -> Path,
179 R: FnMut(&dyn Fn() -> Path, Error),
180 {
181 for (index, value) in self.iter().enumerate() {
182 value.validate_minimally(root, || path().index(index), report);
183 }
184 }
185
186 fn validate_completely<P, R>(&self, root: &Root, path: P, report: &mut R)
187 where
188 P: Fn() -> Path,
189 R: FnMut(&dyn Fn() -> Path, Error),
190 {
191 for (index, value) in self.iter().enumerate() {
192 value.validate_completely(root, || path().index(index), report);
193 }
194 }
195}
196
197impl std::error::Error for Error {
198 fn description(&self) -> &str {
199 match *self {
200 Error::IndexOutOfBounds => "Index out of bounds",
201 Error::Invalid => "Invalid value",
202 Error::Missing => "Missing data",
203 }
204 }
205}
206
207impl std::fmt::Display for Error {
208 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209 use std::error::Error;
210 write!(f, "{}", self.description())
211 }
212}
213
214impl Validate for bool {}
216impl Validate for u32 {}
217impl Validate for i32 {}
218impl Validate for f32 {}
219impl Validate for [f32; 3] {}
220impl Validate for [f32; 4] {}
221impl Validate for [f32; 16] {}
222impl Validate for () {}
223impl Validate for String {}
224impl Validate for serde_json::Value {}