valico/json_schema/validators/
mod.rs1use serde::{Serialize, Serializer};
2use serde_json::{to_value, Value};
3use std::borrow::Cow;
4use std::collections::HashSet;
5use std::fmt;
6
7use super::scope;
8
9#[macro_export]
10macro_rules! strict_process {
11 ($val:expr, $path:ident, $err:expr) => {{
12 let maybe_val = $val;
13 if maybe_val.is_none() {
14 return val_error!($crate::json_schema::errors::WrongType {
15 path: $path.to_string(),
16 detail: $err.to_string()
17 });
18 }
19
20 maybe_val.unwrap()
21 }};
22}
23
24macro_rules! nonstrict_process {
25 ($val:expr, $path:ident) => {{
26 let maybe_val = $val;
27 if maybe_val.is_none() {
28 return $crate::json_schema::validators::ValidationState::new();
29 }
30
31 maybe_val.unwrap()
32 }};
33}
34
35macro_rules! val_error {
36 ($err:expr) => {
37 $crate::json_schema::validators::ValidationState {
38 errors: vec![Box::new($err)],
39 missing: vec![],
40 replacement: None,
41 evaluated: Default::default(),
42 }
43 };
44}
45
46pub use self::conditional::Conditional;
47pub use self::const_::Const;
48pub use self::contains::Contains;
49pub use self::content_media::ContentMedia;
50pub use self::dependencies::Dependencies;
51pub use self::enum_::Enum;
52pub use self::items::Items;
53pub use self::maxmin::{ExclusiveMaximum, ExclusiveMinimum, Maximum, Minimum};
54pub use self::maxmin_items::{MaxItems, MinItems};
55pub use self::maxmin_length::{MaxLength, MinLength};
56pub use self::maxmin_properties::{MaxProperties, MinProperties};
57pub use self::multiple_of::MultipleOf;
58pub use self::not::Not;
59pub use self::of::{AllOf, AnyOf, OneOf};
60pub use self::pattern::Pattern;
61pub use self::properties::Properties;
62pub use self::property_names::PropertyNames;
63pub use self::ref_::Ref;
64pub use self::required::Required;
65pub use self::type_::Type;
66pub use self::unevaluated::Unevaluated;
67pub use self::unique_items::UniqueItems;
68
69mod conditional;
70mod const_;
71mod contains;
72pub mod content_media;
73pub mod dependencies;
74mod enum_;
75pub mod formats;
76pub mod items;
77mod maxmin;
78mod maxmin_items;
79mod maxmin_length;
80mod maxmin_properties;
81mod multiple_of;
82mod not;
83mod of;
84mod pattern;
85pub mod properties;
86mod property_names;
87mod ref_;
88mod required;
89pub mod type_;
90pub mod unevaluated;
91mod unique_items;
92
93#[derive(Debug, Default)]
94pub struct ValidationState {
95 pub errors: super::super::common::error::ValicoErrors,
96 pub missing: Vec<url::Url>,
97 pub replacement: Option<Value>,
98 pub evaluated: HashSet<String>,
101}
102
103impl ValidationState {
104 pub fn new() -> ValidationState {
105 ValidationState {
106 errors: vec![],
107 missing: vec![],
108 replacement: None,
109 evaluated: Default::default(),
110 }
111 }
112
113 pub fn is_valid(&self) -> bool {
114 self.errors.is_empty()
115 }
116
117 pub fn is_strictly_valid(&self) -> bool {
118 self.errors.is_empty() && self.missing.is_empty()
119 }
120
121 pub fn append(&mut self, second: ValidationState) {
122 self.errors.extend(second.errors);
123 self.missing.extend(second.missing);
124 self.evaluated.extend(second.evaluated);
125 }
126
127 pub fn set_replacement<T: Clone + Into<Value>>(&mut self, data: Cow<T>) {
128 if !self.is_valid() {
129 return;
130 }
131 if let Cow::Owned(data) = data {
132 self.replacement = Some(data.into());
133 }
134 }
135}
136
137impl Serialize for ValidationState {
138 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139 where
140 S: Serializer,
141 {
142 let mut map = ::serde_json::Map::new();
143 map.insert(
144 "errors".to_string(),
145 Value::Array(
146 self.errors
147 .iter()
148 .map(|err| to_value(err).unwrap())
149 .collect::<Vec<Value>>(),
150 ),
151 );
152 map.insert(
153 "missing".to_string(),
154 Value::Array(
155 self.missing
156 .iter()
157 .map(|url| to_value(url.to_string()).unwrap())
158 .collect::<Vec<Value>>(),
159 ),
160 );
161 Value::Object(map).serialize(serializer)
162 }
163}
164
165pub trait Validator {
166 fn validate(
167 &self,
168 item: &Value,
169 _: &str,
170 _: &scope::Scope,
171 prev_state: &ValidationState,
172 ) -> ValidationState;
173}
174
175impl fmt::Debug for dyn Validator + 'static + Send + Sync {
176 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
177 fmt.write_str("<validator>")
178 }
179}
180
181pub type BoxedValidator = Box<dyn Validator + 'static + Send + Sync>;
182pub type Validators = Vec<BoxedValidator>;
183
184impl<T> Validator for T
185where
186 T: Fn(&Value, &str, &scope::Scope, &super::ValidationState) -> ValidationState,
187{
188 fn validate(
189 &self,
190 val: &Value,
191 path: &str,
192 scope: &scope::Scope,
193 state: &super::ValidationState,
194 ) -> ValidationState {
195 self(val, path, scope, state)
196 }
197}