corvus_json_schema 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.lock +390 -0
  3. data/Cargo.toml +8 -0
  4. data/LICENSE +201 -0
  5. data/README.md +111 -0
  6. data/VERSIONHISTORY.md +7 -0
  7. data/ext/corvus_json_schema/Cargo.toml +18 -0
  8. data/ext/corvus_json_schema/extconf.rb +6 -0
  9. data/ext/corvus_json_schema/rustfmt.toml +2 -0
  10. data/ext/corvus_json_schema/src/lib.rs +643 -0
  11. data/ext/corvus_json_schema/vendor/corvus-json-schema/Cargo.toml +35 -0
  12. data/ext/corvus_json_schema/vendor/corvus-json-schema/LICENSE +201 -0
  13. data/ext/corvus_json_schema/vendor/corvus-json-schema/README.md +139 -0
  14. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/compiler.rs +1118 -0
  15. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/dialect.rs +108 -0
  16. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/document.rs +905 -0
  17. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/eval/plan/fused.rs +1187 -0
  18. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/eval/plan.rs +1728 -0
  19. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/eval.rs +1451 -0
  20. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/formats.rs +1021 -0
  21. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/instance.rs +228 -0
  22. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/lib.rs +189 -0
  23. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/loader.rs +403 -0
  24. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/metaschemas.rs +29 -0
  25. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/node.rs +417 -0
  26. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/numbers.rs +244 -0
  27. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/options.rs +108 -0
  28. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/pattern.rs +1591 -0
  29. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/results.rs +316 -0
  30. data/ext/corvus_json_schema/vendor/corvus-json-schema/src/uri.rs +274 -0
  31. data/lib/corvus_json_schema/version.rb +5 -0
  32. data/lib/corvus_json_schema.rb +65 -0
  33. metadata +94 -0
@@ -0,0 +1,403 @@
1
+ //! Loads schema documents, identifies resources and anchors, and resolves references.
2
+ //! A port of `SchemaLoader` (via the TypeScript port's `loader.ts`): elements are identified by (document, JSON
3
+ //! pointer), and a value's address identifies it within the compile (documents are boxed and never mutated).
4
+
5
+ use std::collections::HashMap;
6
+
7
+ use serde_json::Value;
8
+
9
+ use crate::dialect::{Dialect, SubschemaKind, known_dialect, subschema_kind, vocab, vocabulary_flag};
10
+ use crate::metaschemas::metaschema;
11
+ use crate::options::{CompileOptions, SchemaCompilationError};
12
+ use crate::uri::{decode_fragment, escape_pointer_token, normalize, resolve, resolve_pointer, split};
13
+
14
+ const DEFAULT_ROOT_URI: &str = "https://corvus-oss.org/runtime-evaluator/root.json";
15
+
16
+ /// The identity of a JSON value within a loaded document.
17
+ #[inline]
18
+ pub(crate) fn addr(v: &Value) -> usize {
19
+ v as *const Value as usize
20
+ }
21
+
22
+ pub(crate) struct SchemaDocument {
23
+ pub root: Box<Value>,
24
+ /// The resource that owns each visited schema value.
25
+ pub resource_of: HashMap<usize, u32>,
26
+ }
27
+
28
+ pub(crate) struct SchemaResource {
29
+ pub document: u32,
30
+ pub root_pointer: String,
31
+ pub uri: String,
32
+ pub dialect: Dialect,
33
+ pub vocabularies: u32,
34
+ pub recursive_anchor: bool,
35
+ pub anchors: HashMap<String, String>,
36
+ pub dynamic_anchors: HashMap<String, String>,
37
+ }
38
+
39
+ /// The target of a reference: a value in a document, and the resource it belongs to.
40
+ #[derive(Clone)]
41
+ pub(crate) struct SchemaTarget {
42
+ pub document: u32,
43
+ pub pointer: String,
44
+ pub value: *const Value,
45
+ pub resource: u32,
46
+ }
47
+
48
+ impl SchemaTarget {
49
+ /// The target value. Valid while the loader that produced the target lives (documents are boxed and
50
+ /// never mutated or dropped before the loader).
51
+ #[inline]
52
+ pub fn value<'a>(&self) -> &'a Value {
53
+ // SAFETY: see above; the compiler never lets a target outlive its loader.
54
+ unsafe { &*self.value }
55
+ }
56
+ }
57
+
58
+ pub(crate) struct SchemaLoader<'o> {
59
+ pub documents: Vec<SchemaDocument>,
60
+ pub resources: Vec<SchemaResource>,
61
+ resources_by_uri: HashMap<String, u32>,
62
+ documents_by_uri: HashMap<String, u32>,
63
+ metaschema_info: HashMap<String, (Dialect, u32)>,
64
+ metaschema_loading: Vec<String>,
65
+ reference_cache: HashMap<(u32, String), Option<SchemaTarget>>,
66
+ options: &'o CompileOptions,
67
+ }
68
+
69
+ fn is_schema_value(v: &Value) -> bool {
70
+ v.is_boolean() || v.is_object()
71
+ }
72
+
73
+ impl<'o> SchemaLoader<'o> {
74
+ pub fn new(options: &'o CompileOptions) -> SchemaLoader<'o> {
75
+ SchemaLoader {
76
+ documents: Vec::new(),
77
+ resources: Vec::new(),
78
+ resources_by_uri: HashMap::new(),
79
+ documents_by_uri: HashMap::new(),
80
+ metaschema_info: HashMap::new(),
81
+ metaschema_loading: Vec::new(),
82
+ reference_cache: HashMap::new(),
83
+ options,
84
+ }
85
+ }
86
+
87
+ pub fn load_root(&mut self, schema: Value, base_uri: Option<&str>) -> Result<u32, SchemaCompilationError> {
88
+ let uri = base_uri.map(normalize).unwrap_or_else(|| DEFAULT_ROOT_URI.to_string());
89
+ let doc = self.add_document(uri, schema)?;
90
+ let d = &self.documents[doc as usize];
91
+ Ok(d.resource_of[&addr(&d.root)])
92
+ }
93
+
94
+ pub fn load_root_from_uri(&mut self, uri: &str) -> Result<u32, SchemaCompilationError> {
95
+ let normalized = normalize(uri);
96
+ if !self.try_load_document(&normalized)? {
97
+ return Err(SchemaCompilationError::new(format!("Unable to resolve the schema document '{uri}'.")));
98
+ }
99
+ let doc = self.documents_by_uri[&normalized];
100
+ let d = &self.documents[doc as usize];
101
+ Ok(d.resource_of[&addr(&d.root)])
102
+ }
103
+
104
+ /// The root value of a resource.
105
+ pub fn resource_root(&self, resource: u32) -> &Value {
106
+ let r = &self.resources[resource as usize];
107
+ let doc = &self.documents[r.document as usize];
108
+ resolve_pointer(&doc.root, &r.root_pointer).map(|(v, _)| v).unwrap_or(&doc.root)
109
+ }
110
+
111
+ pub fn root_target(&self, resource: u32) -> SchemaTarget {
112
+ let r = &self.resources[resource as usize];
113
+ SchemaTarget {
114
+ document: r.document,
115
+ pointer: r.root_pointer.clone(),
116
+ value: self.resource_root(resource) as *const Value,
117
+ resource,
118
+ }
119
+ }
120
+
121
+ pub fn resource_of(&self, document: u32, value: &Value) -> Option<u32> {
122
+ self.documents[document as usize].resource_of.get(&addr(value)).copied()
123
+ }
124
+
125
+ pub fn try_resolve_reference(
126
+ &mut self,
127
+ from: u32,
128
+ reference: &str,
129
+ ) -> Result<Option<SchemaTarget>, SchemaCompilationError> {
130
+ let key = (from, reference.to_string());
131
+ if let Some(t) = self.reference_cache.get(&key) {
132
+ return Ok(t.clone());
133
+ }
134
+ let target = self.resolve_reference(from, reference)?;
135
+ self.reference_cache.insert(key, target.clone());
136
+ Ok(target)
137
+ }
138
+
139
+ fn resolve_reference(
140
+ &mut self,
141
+ from: u32,
142
+ reference: &str,
143
+ ) -> Result<Option<SchemaTarget>, SchemaCompilationError> {
144
+ let (uri_part, fragment) = split(reference);
145
+ let absolute = resolve(&self.resources[from as usize].uri, uri_part);
146
+ let resource = match self.resources_by_uri.get(&absolute) {
147
+ Some(&r) => r,
148
+ None => {
149
+ if !self.try_load_document(&absolute)? {
150
+ return Ok(None);
151
+ }
152
+ match self.resources_by_uri.get(&absolute) {
153
+ Some(&r) => r,
154
+ None => return Ok(None),
155
+ }
156
+ }
157
+ };
158
+ Ok(self.try_resolve_fragment(resource, &decode_fragment(fragment)))
159
+ }
160
+
161
+ pub fn try_resolve_fragment(&self, resource: u32, fragment: &str) -> Option<SchemaTarget> {
162
+ if fragment.is_empty() {
163
+ return Some(self.root_target(resource));
164
+ }
165
+ let r = &self.resources[resource as usize];
166
+ if fragment.starts_with('/') {
167
+ let root = self.resource_root(resource);
168
+ let (value, path) = resolve_pointer(root, fragment)?;
169
+ let owner = self.resource_of(r.document, value).unwrap_or(resource);
170
+ return Some(SchemaTarget {
171
+ document: r.document,
172
+ pointer: format!("{}{}", r.root_pointer, path),
173
+ value: value as *const Value,
174
+ resource: owner,
175
+ });
176
+ }
177
+ let anchor = r.anchors.get(fragment)?;
178
+ let doc = &self.documents[r.document as usize];
179
+ let (value, _) = resolve_pointer(&doc.root, anchor)?;
180
+ Some(SchemaTarget { document: r.document, pointer: anchor.clone(), value: value as *const Value, resource })
181
+ }
182
+
183
+ pub fn get_dialect_info(&mut self, schema_uri: &str) -> Result<(Dialect, u32), SchemaCompilationError> {
184
+ // The standard metaschema URIs, as usually written, need no URI normalisation.
185
+ if let Some(d) = known_dialect(schema_uri.strip_suffix('#').unwrap_or(schema_uri)) {
186
+ return Ok((d, vocab::ALL_ANNOTATING_FORMAT));
187
+ }
188
+ let normalized = normalize(schema_uri);
189
+ if let Some(d) = known_dialect(&normalized) {
190
+ return Ok((d, vocab::ALL_ANNOTATING_FORMAT));
191
+ }
192
+ if let Some(&info) = self.metaschema_info.get(&normalized) {
193
+ return Ok(info);
194
+ }
195
+ if self.metaschema_loading.contains(&normalized) {
196
+ return Ok((self.options.default_dialect, vocab::ALL_ANNOTATING_FORMAT));
197
+ }
198
+ self.metaschema_loading.push(normalized.clone());
199
+ let result = self.load_metaschema_info(&normalized);
200
+ self.metaschema_loading.retain(|u| u != &normalized);
201
+ let info = result?;
202
+ self.metaschema_info.insert(normalized, info);
203
+ Ok(info)
204
+ }
205
+
206
+ fn load_metaschema_info(&mut self, normalized: &str) -> Result<(Dialect, u32), SchemaCompilationError> {
207
+ let meta_resource = match self.resources_by_uri.get(normalized) {
208
+ Some(&r) => r,
209
+ None => {
210
+ if !self.try_load_document(normalized)? {
211
+ return Ok((self.options.default_dialect, vocab::ALL_ANNOTATING_FORMAT));
212
+ }
213
+ match self.resources_by_uri.get(normalized) {
214
+ Some(&r) => r,
215
+ None => return Ok((self.options.default_dialect, vocab::ALL_ANNOTATING_FORMAT)),
216
+ }
217
+ }
218
+ };
219
+ let mut vocabularies = vocab::ALL_ANNOTATING_FORMAT;
220
+ if let Some(Value::Object(v)) = self.resource_root(meta_resource).get("$vocabulary") {
221
+ vocabularies = vocab::NONE;
222
+ for name in v.keys() {
223
+ vocabularies |= vocabulary_flag(name);
224
+ }
225
+ vocabularies |= vocab::CORE;
226
+ }
227
+ Ok((self.resources[meta_resource as usize].dialect, vocabularies))
228
+ }
229
+
230
+ fn try_load_document(&mut self, absolute_uri: &str) -> Result<bool, SchemaCompilationError> {
231
+ if self.documents_by_uri.contains_key(absolute_uri) {
232
+ return Ok(true);
233
+ }
234
+ if let Some(resolver) = &self.options.resolve_document {
235
+ if let Some(doc) = resolver(absolute_uri) {
236
+ self.add_document(absolute_uri.to_string(), doc)?;
237
+ return Ok(true);
238
+ }
239
+ }
240
+ if let Some(text) = metaschema(absolute_uri) {
241
+ let doc: Value = serde_json::from_str(text).expect("embedded metaschemas are valid JSON");
242
+ self.add_document(absolute_uri.to_string(), doc)?;
243
+ return Ok(true);
244
+ }
245
+ Ok(false)
246
+ }
247
+
248
+ fn add_document(&mut self, uri: String, root: Value) -> Result<u32, SchemaCompilationError> {
249
+ let id = self.documents.len() as u32;
250
+ self.documents.push(SchemaDocument { root: Box::new(root), resource_of: HashMap::new() });
251
+ self.documents_by_uri.insert(uri.clone(), id);
252
+ // SAFETY: the boxed root is never moved or dropped while the loader lives.
253
+ let root: &Value = unsafe { &*(self.documents[id as usize].root.as_ref() as *const Value) };
254
+ let (dialect, vocabularies) = match root.get("$schema") {
255
+ Some(Value::String(s)) if root.is_object() => self.get_dialect_info(s)?,
256
+ _ => (self.options.default_dialect, vocab::ALL_ANNOTATING_FORMAT),
257
+ };
258
+ let resource = self.create_resource(id, String::new(), uri, dialect, vocabularies);
259
+ self.walk(id, root, String::new(), resource, true)?;
260
+ Ok(id)
261
+ }
262
+
263
+ fn create_resource(
264
+ &mut self,
265
+ document: u32,
266
+ pointer: String,
267
+ uri: String,
268
+ dialect: Dialect,
269
+ vocabularies: u32,
270
+ ) -> u32 {
271
+ let id = self.resources.len() as u32;
272
+ self.resources.push(SchemaResource {
273
+ document,
274
+ root_pointer: pointer,
275
+ uri: uri.clone(),
276
+ dialect,
277
+ vocabularies,
278
+ recursive_anchor: false,
279
+ anchors: HashMap::new(),
280
+ dynamic_anchors: HashMap::new(),
281
+ });
282
+ self.resources_by_uri.entry(uri).or_insert(id);
283
+ id
284
+ }
285
+
286
+ fn add_anchor(&mut self, resource: u32, name: &str, pointer: &str) {
287
+ self.resources[resource as usize].anchors.entry(name.to_string()).or_insert_with(|| pointer.to_string());
288
+ }
289
+
290
+ fn walk(
291
+ &mut self,
292
+ doc: u32,
293
+ element: &Value,
294
+ pointer: String,
295
+ mut resource: u32,
296
+ mut is_resource_root: bool,
297
+ ) -> Result<(), SchemaCompilationError> {
298
+ let Value::Object(map) = element else {
299
+ self.documents[doc as usize].resource_of.insert(addr(element), resource);
300
+ return Ok(());
301
+ };
302
+
303
+ let (mut dialect, mut vocabularies) = {
304
+ let r = &self.resources[resource as usize];
305
+ (r.dialect, r.vocabularies)
306
+ };
307
+ if !is_resource_root {
308
+ if let Some(Value::String(s)) = map.get("$schema") {
309
+ (dialect, vocabularies) = self.get_dialect_info(s)?;
310
+ }
311
+ }
312
+
313
+ let legacy_ref_overrides_siblings = dialect.is_legacy() && matches!(map.get("$ref"), Some(Value::String(_)));
314
+ if !legacy_ref_overrides_siblings {
315
+ let id_value = if dialect == Dialect::Draft4 { map.get("id") } else { map.get("$id") };
316
+ if let Some(Value::String(id)) = id_value {
317
+ let (uri_part, fragment) = split(id);
318
+ if uri_part.is_empty() {
319
+ if !fragment.is_empty() && dialect.is_legacy() {
320
+ self.add_anchor(resource, fragment, &pointer);
321
+ }
322
+ } else {
323
+ let absolute = resolve(&self.resources[resource as usize].uri, uri_part);
324
+ if !is_resource_root || absolute != self.resources[resource as usize].uri {
325
+ if is_resource_root {
326
+ self.resources_by_uri.entry(absolute.clone()).or_insert(resource);
327
+ self.resources[resource as usize].uri = absolute;
328
+ } else {
329
+ resource = self.create_resource(doc, pointer.clone(), absolute, dialect, vocabularies);
330
+ is_resource_root = true;
331
+ }
332
+ }
333
+ if !fragment.is_empty() && dialect.is_legacy() {
334
+ self.add_anchor(resource, fragment, &pointer);
335
+ }
336
+ }
337
+ }
338
+ if dialect >= Dialect::Draft201909 {
339
+ if let Some(Value::String(a)) = map.get("$anchor") {
340
+ self.add_anchor(resource, a, &pointer);
341
+ }
342
+ }
343
+ if dialect >= Dialect::Draft202012 {
344
+ if let Some(Value::String(name)) = map.get("$dynamicAnchor") {
345
+ self.resources[resource as usize]
346
+ .dynamic_anchors
347
+ .entry(name.clone())
348
+ .or_insert_with(|| pointer.clone());
349
+ self.add_anchor(resource, name, &pointer);
350
+ }
351
+ }
352
+ if dialect == Dialect::Draft201909
353
+ && is_resource_root
354
+ && map.get("$recursiveAnchor") == Some(&Value::Bool(true))
355
+ {
356
+ self.resources[resource as usize].recursive_anchor = true;
357
+ }
358
+ }
359
+
360
+ self.documents[doc as usize].resource_of.insert(addr(element), resource);
361
+
362
+ for (name, value) in map {
363
+ let base = || format!("{pointer}/{}", escape_pointer_token(name));
364
+ match subschema_kind(name, dialect, legacy_ref_overrides_siblings) {
365
+ SubschemaKind::Single => {
366
+ if is_schema_value(value) {
367
+ self.walk(doc, value, base(), resource, false)?;
368
+ }
369
+ }
370
+ SubschemaKind::SingleOrArray => {
371
+ if let Value::Array(items) = value {
372
+ let b = base();
373
+ for (i, v) in items.iter().enumerate() {
374
+ self.walk(doc, v, format!("{b}/{i}"), resource, false)?;
375
+ }
376
+ } else if is_schema_value(value) {
377
+ self.walk(doc, value, base(), resource, false)?;
378
+ }
379
+ }
380
+ SubschemaKind::Array => {
381
+ if let Value::Array(items) = value {
382
+ let b = base();
383
+ for (i, v) in items.iter().enumerate() {
384
+ self.walk(doc, v, format!("{b}/{i}"), resource, false)?;
385
+ }
386
+ }
387
+ }
388
+ SubschemaKind::Map => {
389
+ if let Value::Object(entries) = value {
390
+ let b = base();
391
+ for (entry, v) in entries {
392
+ if is_schema_value(v) {
393
+ self.walk(doc, v, format!("{b}/{}", escape_pointer_token(entry)), resource, false)?;
394
+ }
395
+ }
396
+ }
397
+ }
398
+ SubschemaKind::None => {}
399
+ }
400
+ }
401
+ Ok(())
402
+ }
403
+ }
@@ -0,0 +1,29 @@
1
+ // <auto-generated> by tests/metaschemas.rs from src/Corvus.Text.Json/metaschema. Do not edit.
2
+
3
+ /// The standard metaschemas, keyed by their canonical URI (no trailing empty fragment).
4
+ pub(crate) fn metaschema(uri: &str) -> Option<&'static str> {
5
+ match uri {
6
+ "http://json-schema.org/draft-04/schema" => Some(r####"{"id":"http://json-schema.org/draft-04/schema#","$schema":"http://json-schema.org/draft-04/schema#","description":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"positiveInteger":{"type":"integer","minimum":0},"positiveIntegerDefault0":{"allOf":[{"$ref":"#/definitions/positiveInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true}},"type":"object","properties":{"id":{"type":"string"},"$schema":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"multipleOf":{"type":"number","minimum":0,"exclusiveMinimum":true},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"boolean","default":false},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"boolean","default":false},"maxLength":{"$ref":"#/definitions/positiveInteger"},"minLength":{"$ref":"#/definitions/positiveIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/positiveInteger"},"minItems":{"$ref":"#/definitions/positiveIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxProperties":{"$ref":"#/definitions/positiveInteger"},"minProperties":{"$ref":"#/definitions/positiveIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"dependencies":{"exclusiveMaximum":["maximum"],"exclusiveMinimum":["minimum"]},"default":{}}"####),
7
+ "http://json-schema.org/draft-06/schema" => Some(r####"{"$schema":"http://json-schema.org/draft-06/schema#","$id":"http://json-schema.org/draft-06/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"examples":{"type":"array","items":{}},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":{},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":{}}"####),
8
+ "http://json-schema.org/draft-07/schema" => Some(r####"{"$schema":"http://json-schema.org/draft-07/schema#","$id":"http://json-schema.org/draft-07/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"$comment":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":true,"readOnly":{"type":"boolean","default":false},"writeOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":true},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":true,"enum":{"type":"array","items":true,"minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"if":{"$ref":"#"},"then":{"$ref":"#"},"else":{"$ref":"#"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":true}"####),
9
+ "https://json-schema.org/draft/2019-09/schema" => Some(r####"{"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/schema","$vocabulary":{"https://json-schema.org/draft/2019-09/vocab/core":true,"https://json-schema.org/draft/2019-09/vocab/applicator":true,"https://json-schema.org/draft/2019-09/vocab/validation":true,"https://json-schema.org/draft/2019-09/vocab/meta-data":true,"https://json-schema.org/draft/2019-09/vocab/format":false,"https://json-schema.org/draft/2019-09/vocab/content":true},"$recursiveAnchor":true,"title":"Core and Validation specifications meta-schema","allOf":[{"$ref":"meta/core"},{"$ref":"meta/applicator"},{"$ref":"meta/validation"},{"$ref":"meta/meta-data"},{"$ref":"meta/format"},{"$ref":"meta/content"}],"type":["object","boolean"],"properties":{"definitions":{"$comment":"While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.","type":"object","additionalProperties":{"$recursiveRef":"#"},"default":{}},"dependencies":{"$comment":"\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"","type":"object","additionalProperties":{"anyOf":[{"$recursiveRef":"#"},{"$ref":"meta/validation#/$defs/stringArray"}]}}}}"####),
10
+ "https://json-schema.org/draft/2020-12/schema" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/schema","$vocabulary":{"https://json-schema.org/draft/2020-12/vocab/core":true,"https://json-schema.org/draft/2020-12/vocab/applicator":true,"https://json-schema.org/draft/2020-12/vocab/unevaluated":true,"https://json-schema.org/draft/2020-12/vocab/validation":true,"https://json-schema.org/draft/2020-12/vocab/meta-data":true,"https://json-schema.org/draft/2020-12/vocab/format-annotation":true,"https://json-schema.org/draft/2020-12/vocab/content":true},"$dynamicAnchor":"meta","title":"Core and Validation specifications meta-schema","allOf":[{"$ref":"meta/core"},{"$ref":"meta/applicator"},{"$ref":"meta/unevaluated"},{"$ref":"meta/validation"},{"$ref":"meta/meta-data"},{"$ref":"meta/format-annotation"},{"$ref":"meta/content"}],"type":["object","boolean"],"$comment":"This meta-schema also defines keywords that have appeared in previous drafts in order to prevent incompatible extensions as they remain in common use.","properties":{"definitions":{"$comment":"\"definitions\" has been replaced by \"$defs\".","type":"object","additionalProperties":{"$dynamicRef":"#meta"},"deprecated":true,"default":{}},"dependencies":{"$comment":"\"dependencies\" has been split and replaced by \"dependentSchemas\" and \"dependentRequired\" in order to serve their differing semantics.","type":"object","additionalProperties":{"anyOf":[{"$dynamicRef":"#meta"},{"$ref":"meta/validation#/$defs/stringArray"}]},"deprecated":true,"default":{}},"$recursiveAnchor":{"$comment":"\"$recursiveAnchor\" has been replaced by \"$dynamicAnchor\".","$ref":"meta/core#/$defs/anchorString","deprecated":true},"$recursiveRef":{"$comment":"\"$recursiveRef\" has been replaced by \"$dynamicRef\".","$ref":"meta/core#/$defs/uriReferenceString","deprecated":true}}}"####),
11
+ "https://json-schema.org/draft/2019-09/meta/applicator" => Some(r####"{"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/meta/applicator","$recursiveAnchor":true,"title":"Applicator vocabulary meta-schema","type":["object","boolean"],"properties":{"additionalItems":{"$recursiveRef":"#"},"unevaluatedItems":{"$recursiveRef":"#"},"items":{"anyOf":[{"$recursiveRef":"#"},{"$ref":"#/$defs/schemaArray"}]},"contains":{"$recursiveRef":"#"},"additionalProperties":{"$recursiveRef":"#"},"unevaluatedProperties":{"$recursiveRef":"#"},"properties":{"type":"object","additionalProperties":{"$recursiveRef":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$recursiveRef":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependentSchemas":{"type":"object","additionalProperties":{"$recursiveRef":"#"}},"propertyNames":{"$recursiveRef":"#"},"if":{"$recursiveRef":"#"},"then":{"$recursiveRef":"#"},"else":{"$recursiveRef":"#"},"allOf":{"$ref":"#/$defs/schemaArray"},"anyOf":{"$ref":"#/$defs/schemaArray"},"oneOf":{"$ref":"#/$defs/schemaArray"},"not":{"$recursiveRef":"#"}},"$defs":{"schemaArray":{"type":"array","minItems":1,"items":{"$recursiveRef":"#"}}}}"####),
12
+ "https://json-schema.org/draft/2019-09/meta/content" => Some(r####"{"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/meta/content","$recursiveAnchor":true,"title":"Content vocabulary meta-schema","type":["object","boolean"],"properties":{"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"contentSchema":{"$recursiveRef":"#"}}}"####),
13
+ "https://json-schema.org/draft/2019-09/meta/core" => Some(r####"{"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/meta/core","$recursiveAnchor":true,"title":"Core vocabulary meta-schema","type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference","$comment":"Non-empty fragments not allowed.","pattern":"^[^#]*#?$"},"$schema":{"type":"string","format":"uri"},"$anchor":{"type":"string","pattern":"^[A-Za-z][-A-Za-z0-9.:_]*$"},"$ref":{"type":"string","format":"uri-reference"},"$recursiveRef":{"type":"string","format":"uri-reference"},"$recursiveAnchor":{"type":"boolean","default":false},"$vocabulary":{"type":"object","propertyNames":{"type":"string","format":"uri"},"additionalProperties":{"type":"boolean"}},"$comment":{"type":"string"},"$defs":{"type":"object","additionalProperties":{"$recursiveRef":"#"},"default":{}}}}"####),
14
+ "https://json-schema.org/draft/2019-09/meta/format" => Some(r####"{"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/meta/format","$recursiveAnchor":true,"title":"Format vocabulary meta-schema","type":["object","boolean"],"properties":{"format":{"type":"string"}}}"####),
15
+ "https://json-schema.org/draft/2019-09/meta/hyper-schema" => Some(r####"{"$schema":"https://json-schema.org/draft/2019-09/hyper-schema","$id":"https://json-schema.org/draft/2019-09/meta/hyper-schema","$recursiveAnchor":true,"title":"JSON Hyper-Schema Vocabulary Schema","type":["object","boolean"],"properties":{"base":{"type":"string","format":"uri-template"},"links":{"type":"array","items":{"$ref":"https://json-schema.org/draft/2019-09/links"}}},"links":[{"rel":"self","href":"{+%24id}"}]}"####),
16
+ "https://json-schema.org/draft/2019-09/meta/meta-data" => Some(r####"{"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/meta/meta-data","$recursiveAnchor":true,"title":"Meta-data vocabulary meta-schema","type":["object","boolean"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"default":true,"deprecated":{"type":"boolean","default":false},"readOnly":{"type":"boolean","default":false},"writeOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true}}}"####),
17
+ "https://json-schema.org/draft/2019-09/meta/validation" => Some(r####"{"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/meta/validation","$recursiveAnchor":true,"title":"Validation vocabulary meta-schema","type":["object","boolean"],"properties":{"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/$defs/nonNegativeInteger"},"minLength":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"maxItems":{"$ref":"#/$defs/nonNegativeInteger"},"minItems":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxContains":{"$ref":"#/$defs/nonNegativeInteger"},"minContains":{"$ref":"#/$defs/nonNegativeInteger","default":1},"maxProperties":{"$ref":"#/$defs/nonNegativeInteger"},"minProperties":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"required":{"$ref":"#/$defs/stringArray"},"dependentRequired":{"type":"object","additionalProperties":{"$ref":"#/$defs/stringArray"}},"const":true,"enum":{"type":"array","items":true},"type":{"anyOf":[{"$ref":"#/$defs/simpleTypes"},{"type":"array","items":{"$ref":"#/$defs/simpleTypes"},"minItems":1,"uniqueItems":true}]}},"$defs":{"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"$ref":"#/$defs/nonNegativeInteger","default":0},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}}}"####),
18
+ "https://json-schema.org/draft/2020-12/meta/applicator" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/applicator","$dynamicAnchor":"meta","title":"Applicator vocabulary meta-schema","type":["object","boolean"],"properties":{"prefixItems":{"$ref":"#/$defs/schemaArray"},"items":{"$dynamicRef":"#meta"},"contains":{"$dynamicRef":"#meta"},"additionalProperties":{"$dynamicRef":"#meta"},"properties":{"type":"object","additionalProperties":{"$dynamicRef":"#meta"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$dynamicRef":"#meta"},"propertyNames":{"format":"regex"},"default":{}},"dependentSchemas":{"type":"object","additionalProperties":{"$dynamicRef":"#meta"},"default":{}},"propertyNames":{"$dynamicRef":"#meta"},"if":{"$dynamicRef":"#meta"},"then":{"$dynamicRef":"#meta"},"else":{"$dynamicRef":"#meta"},"allOf":{"$ref":"#/$defs/schemaArray"},"anyOf":{"$ref":"#/$defs/schemaArray"},"oneOf":{"$ref":"#/$defs/schemaArray"},"not":{"$dynamicRef":"#meta"}},"$defs":{"schemaArray":{"type":"array","minItems":1,"items":{"$dynamicRef":"#meta"}}}}"####),
19
+ "https://json-schema.org/draft/2020-12/meta/content" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/content","$dynamicAnchor":"meta","title":"Content vocabulary meta-schema","type":["object","boolean"],"properties":{"contentEncoding":{"type":"string"},"contentMediaType":{"type":"string"},"contentSchema":{"$dynamicRef":"#meta"}}}"####),
20
+ "https://json-schema.org/draft/2020-12/meta/core" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/core","$dynamicAnchor":"meta","title":"Core vocabulary meta-schema","type":["object","boolean"],"properties":{"$id":{"$ref":"#/$defs/uriReferenceString","$comment":"Non-empty fragments not allowed.","pattern":"^[^#]*#?$"},"$schema":{"$ref":"#/$defs/uriString"},"$ref":{"$ref":"#/$defs/uriReferenceString"},"$anchor":{"$ref":"#/$defs/anchorString"},"$dynamicRef":{"$ref":"#/$defs/uriReferenceString"},"$dynamicAnchor":{"$ref":"#/$defs/anchorString"},"$vocabulary":{"type":"object","propertyNames":{"$ref":"#/$defs/uriString"},"additionalProperties":{"type":"boolean"}},"$comment":{"type":"string"},"$defs":{"type":"object","additionalProperties":{"$dynamicRef":"#meta"}}},"$defs":{"anchorString":{"type":"string","pattern":"^[A-Za-z_][-A-Za-z0-9._]*$"},"uriString":{"type":"string","format":"uri"},"uriReferenceString":{"type":"string","format":"uri-reference"}}}"####),
21
+ "https://json-schema.org/draft/2020-12/meta/format-annotation" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/format-annotation","$dynamicAnchor":"meta","title":"Format vocabulary meta-schema for annotation results","type":["object","boolean"],"properties":{"format":{"type":"string"}}}"####),
22
+ "https://json-schema.org/draft/2020-12/meta/format-assertion" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/format-assertion","$dynamicAnchor":"meta","title":"Format vocabulary meta-schema for assertion results","type":["object","boolean"],"properties":{"format":{"type":"string"}}}"####),
23
+ "https://json-schema.org/draft/2020-12/meta/hyper-schema" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/hyper-schema","$id":"https://json-schema.org/draft/2020-12/meta/hyper-schema","$dynamicAnchor":"meta","title":"JSON Hyper-Schema Vocabulary Schema","type":["object","boolean"],"properties":{"base":{"type":"string","format":"uri-template"},"links":{"type":"array","items":{"$ref":"https://json-schema.org/draft/2020-12/links"}}},"links":[{"rel":"self","href":"{+%24id}"}]}"####),
24
+ "https://json-schema.org/draft/2020-12/meta/meta-data" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/meta-data","$dynamicAnchor":"meta","title":"Meta-data vocabulary meta-schema","type":["object","boolean"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"default":true,"deprecated":{"type":"boolean","default":false},"readOnly":{"type":"boolean","default":false},"writeOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true}}}"####),
25
+ "https://json-schema.org/draft/2020-12/meta/unevaluated" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/unevaluated","$dynamicAnchor":"meta","title":"Unevaluated applicator vocabulary meta-schema","type":["object","boolean"],"properties":{"unevaluatedItems":{"$dynamicRef":"#meta"},"unevaluatedProperties":{"$dynamicRef":"#meta"}}}"####),
26
+ "https://json-schema.org/draft/2020-12/meta/validation" => Some(r####"{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/validation","$dynamicAnchor":"meta","title":"Validation vocabulary meta-schema","type":["object","boolean"],"properties":{"type":{"anyOf":[{"$ref":"#/$defs/simpleTypes"},{"type":"array","items":{"$ref":"#/$defs/simpleTypes"},"minItems":1,"uniqueItems":true}]},"const":true,"enum":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/$defs/nonNegativeInteger"},"minLength":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"maxItems":{"$ref":"#/$defs/nonNegativeInteger"},"minItems":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxContains":{"$ref":"#/$defs/nonNegativeInteger"},"minContains":{"$ref":"#/$defs/nonNegativeInteger","default":1},"maxProperties":{"$ref":"#/$defs/nonNegativeInteger"},"minProperties":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"required":{"$ref":"#/$defs/stringArray"},"dependentRequired":{"type":"object","additionalProperties":{"$ref":"#/$defs/stringArray"}}},"$defs":{"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"$ref":"#/$defs/nonNegativeInteger","default":0},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}}}"####),
27
+ _ => None,
28
+ }
29
+ }