valico/json_schema/keywords/
mod.rs1use serde_json::Value;
2use std::any;
3use std::collections;
4use std::fmt;
5use std::sync::Arc;
6
7use super::schema;
8use super::validators;
9use super::SchemaVersion;
10
11pub type KeywordResult = Result<Option<validators::BoxedValidator>, schema::SchemaError>;
12pub type KeywordPair = (Vec<&'static str>, Box<dyn Keyword + 'static>);
13pub type KeywordPairs = Vec<KeywordPair>;
14pub type KeywordMap = collections::HashMap<&'static str, Arc<KeywordConsumer>>;
15
16pub trait Keyword: Send + Sync + any::Any {
17 fn compile(&self, def: &Value, ctx: &schema::WalkContext) -> KeywordResult;
18 fn is_exclusive(&self, _version: SchemaVersion) -> bool {
19 false
20 }
21 fn place_first(&self) -> bool {
22 false
23 }
24 fn place_last(&self) -> bool {
25 false
26 }
27}
28
29impl<T: 'static + Send + Sync + any::Any> Keyword for T
30where
31 T: Fn(&Value, &schema::WalkContext<'_>) -> KeywordResult,
32{
33 fn compile(&self, def: &Value, ctx: &schema::WalkContext<'_>) -> KeywordResult {
34 self(def, ctx)
35 }
36}
37
38impl fmt::Debug for dyn Keyword + 'static {
39 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
40 fmt.write_str("<keyword>")
41 }
42}
43
44macro_rules! keyword_key_exists {
45 ($val:expr, $key:expr) => {{
46 let maybe_val = $val.get($key);
47 if let Some(maybe_val) = maybe_val {
48 maybe_val
49 } else {
50 return Ok(None);
51 }
52 }};
53}
54
55#[macro_use]
56pub mod maxmin_length;
57
58pub mod conditional;
59pub mod const_;
60pub mod contains;
61pub mod content_media;
62pub mod dependencies;
63pub mod enum_;
64pub mod format;
65pub mod items;
66pub mod maxmin;
67pub mod maxmin_items;
68pub mod maxmin_properties;
69pub mod multiple_of;
70pub mod not;
71pub mod of;
72pub mod pattern;
73pub mod properties;
74pub mod property_names;
75pub mod ref_;
76pub mod required;
77pub mod type_;
78mod unevaluated;
79pub mod unique_items;
80
81pub fn default() -> KeywordMap {
82 let mut map = collections::HashMap::new();
83
84 decouple_keyword((vec!["$ref"], Box::new(ref_::Ref)), &mut map);
85 decouple_keyword((vec!["allOf"], Box::new(of::AllOf)), &mut map);
86 decouple_keyword((vec!["anyOf"], Box::new(of::AnyOf)), &mut map);
87 decouple_keyword((vec!["const"], Box::new(const_::Const)), &mut map);
88 decouple_keyword(
89 (
90 vec!["contains", "minContains", "maxContains"],
91 Box::new(contains::Contains),
92 ),
93 &mut map,
94 );
95 decouple_keyword(
96 (
97 vec!["dependencies", "dependentRequired", "dependentSchemas"],
98 Box::new(dependencies::Dependencies),
99 ),
100 &mut map,
101 );
102 decouple_keyword((vec!["enum"], Box::new(enum_::Enum)), &mut map);
103 decouple_keyword(
104 (vec!["exclusiveMaximum"], Box::new(maxmin::ExclusiveMaximum)),
105 &mut map,
106 );
107 decouple_keyword(
108 (vec!["exclusiveMinimum"], Box::new(maxmin::ExclusiveMinimum)),
109 &mut map,
110 );
111 decouple_keyword(
112 (vec!["items", "additionalItems"], Box::new(items::Items)),
113 &mut map,
114 );
115 decouple_keyword(
116 (vec!["maxItems"], Box::new(maxmin_items::MaxItems)),
117 &mut map,
118 );
119 decouple_keyword(
120 (vec!["maxLength"], Box::new(maxmin_length::MaxLength)),
121 &mut map,
122 );
123 decouple_keyword(
124 (
125 vec!["maxProperties"],
126 Box::new(maxmin_properties::MaxProperties),
127 ),
128 &mut map,
129 );
130 decouple_keyword((vec!["maximum"], Box::new(maxmin::Maximum)), &mut map);
131 decouple_keyword(
132 (vec!["minItems"], Box::new(maxmin_items::MinItems)),
133 &mut map,
134 );
135 decouple_keyword(
136 (vec!["minLength"], Box::new(maxmin_length::MinLength)),
137 &mut map,
138 );
139 decouple_keyword(
140 (
141 vec!["minProperties"],
142 Box::new(maxmin_properties::MinProperties),
143 ),
144 &mut map,
145 );
146 decouple_keyword((vec!["minimum"], Box::new(maxmin::Minimum)), &mut map);
147 decouple_keyword(
148 (vec!["multipleOf"], Box::new(multiple_of::MultipleOf)),
149 &mut map,
150 );
151 decouple_keyword((vec!["not"], Box::new(not::Not)), &mut map);
152 decouple_keyword((vec!["oneOf"], Box::new(of::OneOf)), &mut map);
153 decouple_keyword((vec!["pattern"], Box::new(pattern::Pattern)), &mut map);
154 decouple_keyword(
155 (
156 vec!["properties", "additionalProperties", "patternProperties"],
157 Box::new(properties::Properties),
158 ),
159 &mut map,
160 );
161 decouple_keyword(
162 (
163 vec!["propertyNames"],
164 Box::new(property_names::PropertyNames),
165 ),
166 &mut map,
167 );
168 decouple_keyword((vec!["required"], Box::new(required::Required)), &mut map);
169 decouple_keyword((vec!["type"], Box::new(type_::Type)), &mut map);
170 decouple_keyword(
171 (
172 vec!["unevaluatedItems"],
173 Box::new(unevaluated::UnevaluatedItems),
174 ),
175 &mut map,
176 );
177 decouple_keyword(
178 (
179 vec!["unevaluatedProperties"],
180 Box::new(unevaluated::UnevaluatedProperties),
181 ),
182 &mut map,
183 );
184
185 decouple_keyword(
186 (vec!["uniqueItems"], Box::new(unique_items::UniqueItems)),
187 &mut map,
188 );
189
190 decouple_keyword(
191 (
192 vec!["contentMediaType", "contentEncoding"],
193 Box::new(content_media::ContentMedia),
194 ),
195 &mut map,
196 );
197
198 decouple_keyword(
199 (
200 vec!["if", "then", "else"],
201 Box::new(conditional::Conditional),
202 ),
203 &mut map,
204 );
205
206 map
207}
208
209#[derive(Debug)]
210pub struct KeywordConsumer {
211 pub keys: Vec<&'static str>,
212 pub keyword: Box<dyn Keyword + 'static>,
213}
214
215impl KeywordConsumer {
216 pub fn consume(&self, set: &mut collections::HashSet<&str>) {
217 for key in self.keys.iter() {
218 if set.contains(key) {
219 set.remove(key);
220 }
221 }
222 }
223}
224
225pub fn decouple_keyword(keyword_pair: KeywordPair, map: &mut KeywordMap) {
226 let (keys, keyword) = keyword_pair;
227
228 let consumer = Arc::new(KeywordConsumer {
229 keys: keys.clone(),
230 keyword,
231 });
232
233 for key in keys.iter() {
234 map.insert(key, consumer.clone());
235 }
236}