Skip to main content

valico/json_schema/keywords/
mod.rs

1use 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}