vector_config_common/schema/
json_schema.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::{iter, ops::Deref};
4
5use super::{Map, Set, DEFINITIONS_PREFIX};
6
7/// A JSON Schema.
8#[allow(clippy::large_enum_variant)]
9#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
10#[serde(untagged)]
11pub enum Schema {
12    /// A trivial boolean JSON Schema.
13    ///
14    /// The schema `true` matches everything (always passes validation), whereas the schema `false`
15    /// matches nothing (always fails validation).
16    Bool(bool),
17
18    /// A JSON Schema object.
19    Object(SchemaObject),
20}
21
22impl Schema {
23    /// Creates a new `$ref` schema.
24    ///
25    /// The given reference string should be a URI reference. This will usually be a JSON Pointer
26    /// in [URI Fragment representation](https://tools.ietf.org/html/rfc6901#section-6).
27    pub fn new_ref(reference: String) -> Self {
28        SchemaObject::new_ref(reference).into()
29    }
30
31    /// Returns `true` if `self` is a `$ref` schema.
32    ///
33    /// If `self` is a [`SchemaObject`] with `Some`
34    /// [`reference`](struct.SchemaObject.html#structfield.reference) set, this returns `true`.
35    /// Otherwise, returns `false`.
36    pub fn is_ref(&self) -> bool {
37        match self {
38            Schema::Object(o) => o.is_ref(),
39            _ => false,
40        }
41    }
42
43    /// Gets a reference to the inner schema object if this schema is a JSON Schema object.
44    ///
45    /// Otherwise, `None` is returned.
46    pub fn as_object(&self) -> Option<&SchemaObject> {
47        match self {
48            Schema::Object(schema) => Some(schema),
49            _ => None,
50        }
51    }
52
53    /// Gets a mutable reference to the inner schema object if this schema is a JSON Schema object.
54    ///
55    /// Otherwise, `None` is returned.
56    pub fn as_object_mut(&mut self) -> Option<&mut SchemaObject> {
57        match self {
58            Schema::Object(schema) => Some(schema),
59            _ => None,
60        }
61    }
62
63    /// Converts the given schema (if it is a boolean schema) into an equivalent schema object.
64    ///
65    /// If the given schema is already a schema object, this has no effect.
66    pub fn into_object(self) -> SchemaObject {
67        match self {
68            Schema::Object(o) => o,
69            Schema::Bool(true) => SchemaObject::default(),
70            Schema::Bool(false) => SchemaObject {
71                subschemas: Some(Box::new(SubschemaValidation {
72                    not: Some(Schema::Object(Default::default()).into()),
73                    ..Default::default()
74                })),
75                ..Default::default()
76            },
77        }
78    }
79}
80
81impl From<SchemaObject> for Schema {
82    fn from(o: SchemaObject) -> Self {
83        Schema::Object(o)
84    }
85}
86
87impl From<bool> for Schema {
88    fn from(b: bool) -> Self {
89        Schema::Bool(b)
90    }
91}
92
93/// The root object of a JSON Schema document.
94#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
95#[serde(rename_all = "camelCase", default)]
96pub struct RootSchema {
97    /// The `$schema` keyword.
98    ///
99    /// See [JSON Schema 8.1.1. The "$schema" Keyword](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.1.1).
100    #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")]
101    pub meta_schema: Option<String>,
102
103    /// The root schema itself.
104    #[serde(flatten)]
105    pub schema: SchemaObject,
106
107    /// The `definitions` keyword.
108    ///
109    /// In JSON Schema draft 2019-09 this was replaced by $defs, but in Schemars this is still
110    /// serialized as `definitions` for backward-compatibility.
111    ///
112    /// See [JSON Schema 8.2.5. Schema Re-Use With "$defs"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.5),
113    /// and [JSON Schema (draft 07) 9. Schema Re-Use With "definitions"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-9).
114    #[serde(alias = "$defs", skip_serializing_if = "Map::is_empty")]
115    pub definitions: Map<String, Schema>,
116}
117
118/// A JSON Schema object.
119#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
120#[serde(rename_all = "camelCase", default)]
121pub struct SchemaObject {
122    /// Properties which annotate the [`SchemaObject`] which typically have no effect when an object is being validated against the schema.
123    #[serde(flatten, deserialize_with = "skip_if_default")]
124    pub metadata: Option<Box<Metadata>>,
125
126    /// The `type` keyword.
127    ///
128    /// See [JSON Schema Validation 6.1.1. "type"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.1)
129    /// and [JSON Schema 4.2.1. Instance Data Model](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-4.2.1).
130    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
131    pub instance_type: Option<SingleOrVec<InstanceType>>,
132
133    /// The `format` keyword.
134    ///
135    /// See [JSON Schema Validation 7. A Vocabulary for Semantic Content With "format"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-7).
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub format: Option<String>,
138
139    /// The `enum` keyword.
140    ///
141    /// See [JSON Schema Validation 6.1.2. "enum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.2)
142    #[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
143    pub enum_values: Option<Vec<Value>>,
144
145    /// The `const` keyword.
146    ///
147    /// See [JSON Schema Validation 6.1.3. "const"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.1.3)
148    #[serde(
149        rename = "const",
150        skip_serializing_if = "Option::is_none",
151        deserialize_with = "allow_null"
152    )]
153    pub const_value: Option<Value>,
154
155    /// Properties of the [`SchemaObject`] which define validation assertions in terms of other schemas.
156    #[serde(flatten, deserialize_with = "skip_if_default")]
157    pub subschemas: Option<Box<SubschemaValidation>>,
158
159    /// Properties of the [`SchemaObject`] which define validation assertions for numbers.
160    #[serde(flatten, deserialize_with = "skip_if_default")]
161    pub number: Option<Box<NumberValidation>>,
162
163    /// Properties of the [`SchemaObject`] which define validation assertions for strings.
164    #[serde(flatten, deserialize_with = "skip_if_default")]
165    pub string: Option<Box<StringValidation>>,
166
167    /// Properties of the [`SchemaObject`] which define validation assertions for arrays.
168    #[serde(flatten, deserialize_with = "skip_if_default")]
169    pub array: Option<Box<ArrayValidation>>,
170
171    /// Properties of the [`SchemaObject`] which define validation assertions for objects.
172    #[serde(flatten, deserialize_with = "skip_if_default")]
173    pub object: Option<Box<ObjectValidation>>,
174
175    /// The `$ref` keyword.
176    ///
177    /// See [JSON Schema 8.2.4.1. Direct References with "$ref"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.4.1).
178    #[serde(rename = "$ref", skip_serializing_if = "Option::is_none")]
179    pub reference: Option<String>,
180
181    /// Arbitrary extra properties which are not part of the JSON Schema specification, or which `schemars` does not support.
182    #[serde(flatten)]
183    pub extensions: Map<String, Value>,
184}
185
186// Deserializing "null" to `Option<Value>` directly results in `None`,
187// this function instead makes it deserialize to `Some(Value::Null)`.
188fn allow_null<'de, D>(de: D) -> Result<Option<Value>, D::Error>
189where
190    D: serde::Deserializer<'de>,
191{
192    Value::deserialize(de).map(Option::Some)
193}
194
195fn skip_if_default<'de, D, T>(deserializer: D) -> Result<Option<Box<T>>, D::Error>
196where
197    D: serde::Deserializer<'de>,
198    T: Deserialize<'de> + Default + PartialEq,
199{
200    let value = T::deserialize(deserializer)?;
201    Ok((value != T::default()).then(|| Box::new(value)))
202}
203
204macro_rules! get_or_insert_default_fn {
205    ($name:ident, $ret:ty) => {
206        get_or_insert_default_fn!(
207            concat!(
208                "Returns a mutable reference to this schema's [`",
209                stringify!($ret),
210                "`](#structfield.",
211                stringify!($name),
212                "), creating it if it was `None`."
213            ),
214            $name,
215            $ret
216        );
217    };
218    ($doc:expr, $name:ident, $ret:ty) => {
219        #[doc = $doc]
220        pub fn $name(&mut self) -> &mut $ret {
221            self.$name.get_or_insert_with(Default::default)
222        }
223    };
224}
225
226impl SchemaObject {
227    /// Creates a new `$ref` schema.
228    ///
229    /// The given reference string should be a URI reference. This will usually be a JSON Pointer
230    /// in [URI Fragment representation](https://tools.ietf.org/html/rfc6901#section-6).
231    pub fn new_ref(reference: String) -> Self {
232        SchemaObject {
233            reference: Some(reference),
234            ..Default::default()
235        }
236    }
237
238    /// Returns `true` if `self` is a `$ref` schema.
239    ///
240    /// If `self` has `Some` [`reference`](struct.SchemaObject.html#structfield.reference) set, this returns `true`.
241    /// Otherwise, returns `false`.
242    pub fn is_ref(&self) -> bool {
243        self.reference.is_some()
244    }
245
246    /// Returns `true` if `self` accepts values of the given type, according to the [`Self::instance_type`] field.
247    ///
248    /// This is a basic check that always returns `true` if no `instance_type` is specified on the schema,
249    /// and does not check any subschemas. Because of this, both `{}` and  `{"not": {}}` accept any type according
250    /// to this method.
251    pub fn has_type(&self, ty: InstanceType) -> bool {
252        self.instance_type.as_ref().is_none_or(|x| x.contains(&ty))
253    }
254
255    get_or_insert_default_fn!(metadata, Metadata);
256    get_or_insert_default_fn!(subschemas, SubschemaValidation);
257    get_or_insert_default_fn!(number, NumberValidation);
258    get_or_insert_default_fn!(string, StringValidation);
259    get_or_insert_default_fn!(array, ArrayValidation);
260    get_or_insert_default_fn!(object, ObjectValidation);
261}
262
263impl From<Schema> for SchemaObject {
264    fn from(schema: Schema) -> Self {
265        schema.into_object()
266    }
267}
268
269/// Properties which annotate a [`SchemaObject`] which typically have no effect when an object is being validated against the schema.
270#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
271#[serde(rename_all = "camelCase", default)]
272pub struct Metadata {
273    /// The `$id` keyword.
274    ///
275    /// See [JSON Schema 8.2.2. The "$id" Keyword](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.2).
276    #[serde(rename = "$id", skip_serializing_if = "Option::is_none")]
277    pub id: Option<String>,
278
279    /// The `title` keyword.
280    ///
281    /// See [JSON Schema Validation 9.1. "title" and "description"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.1).
282    #[serde(skip_serializing_if = "Option::is_none")]
283    pub title: Option<String>,
284
285    /// The `description` keyword.
286    ///
287    /// See [JSON Schema Validation 9.1. "title" and "description"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.1).
288    #[serde(skip_serializing_if = "Option::is_none")]
289    pub description: Option<String>,
290
291    /// The `default` keyword.
292    ///
293    /// See [JSON Schema Validation 9.2. "default"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.2).
294    #[serde(
295        skip_serializing_if = "Option::is_none",
296        deserialize_with = "allow_null"
297    )]
298    pub default: Option<Value>,
299
300    /// The `deprecated` keyword.
301    ///
302    /// See [JSON Schema Validation 9.3. "deprecated"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.3).
303    #[serde(skip_serializing_if = "is_false")]
304    pub deprecated: bool,
305
306    /// The `readOnly` keyword.
307    ///
308    /// See [JSON Schema Validation 9.4. "readOnly" and "writeOnly"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.4).
309    #[serde(skip_serializing_if = "is_false")]
310    pub read_only: bool,
311
312    /// The `writeOnly` keyword.
313    ///
314    /// See [JSON Schema Validation 9.4. "readOnly" and "writeOnly"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.4).
315    #[serde(skip_serializing_if = "is_false")]
316    pub write_only: bool,
317
318    /// The `examples` keyword.
319    ///
320    /// See [JSON Schema Validation 9.5. "examples"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.5).
321    #[serde(skip_serializing_if = "Vec::is_empty")]
322    pub examples: Vec<Value>,
323}
324
325#[allow(clippy::trivially_copy_pass_by_ref)]
326fn is_false(b: &bool) -> bool {
327    !b
328}
329
330/// Properties of a [`SchemaObject`] which define validation assertions in terms of other schemas.
331#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
332#[serde(rename_all = "camelCase", default)]
333pub struct SubschemaValidation {
334    /// The `allOf` keyword.
335    ///
336    /// See [JSON Schema 9.2.1.1. "allOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.1).
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub all_of: Option<Vec<Schema>>,
339
340    /// The `anyOf` keyword.
341    ///
342    /// See [JSON Schema 9.2.1.2. "anyOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.2).
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub any_of: Option<Vec<Schema>>,
345
346    /// The `oneOf` keyword.
347    ///
348    /// See [JSON Schema 9.2.1.3. "oneOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.3).
349    #[serde(skip_serializing_if = "Option::is_none")]
350    pub one_of: Option<Vec<Schema>>,
351
352    /// The `not` keyword.
353    ///
354    /// See [JSON Schema 9.2.1.4. "not"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.4).
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub not: Option<Box<Schema>>,
357
358    /// The `if` keyword.
359    ///
360    /// See [JSON Schema 9.2.2.1. "if"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.1).
361    #[serde(rename = "if", skip_serializing_if = "Option::is_none")]
362    pub if_schema: Option<Box<Schema>>,
363
364    /// The `then` keyword.
365    ///
366    /// See [JSON Schema 9.2.2.2. "then"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.2).
367    #[serde(rename = "then", skip_serializing_if = "Option::is_none")]
368    pub then_schema: Option<Box<Schema>>,
369
370    /// The `else` keyword.
371    ///
372    /// See [JSON Schema 9.2.2.3. "else"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.3).
373    #[serde(rename = "else", skip_serializing_if = "Option::is_none")]
374    pub else_schema: Option<Box<Schema>>,
375}
376
377/// Properties of a [`SchemaObject`] which define validation assertions for numbers.
378#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
379#[serde(rename_all = "camelCase", default)]
380pub struct NumberValidation {
381    /// The `multipleOf` keyword.
382    ///
383    /// See [JSON Schema Validation 6.2.1. "multipleOf"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.1).
384    #[serde(skip_serializing_if = "Option::is_none")]
385    pub multiple_of: Option<f64>,
386
387    /// The `maximum` keyword.
388    ///
389    /// See [JSON Schema Validation 6.2.2. "maximum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.2).
390    #[serde(skip_serializing_if = "Option::is_none")]
391    pub maximum: Option<f64>,
392
393    /// The `exclusiveMaximum` keyword.
394    ///
395    /// See [JSON Schema Validation 6.2.3. "exclusiveMaximum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.3).
396    #[serde(skip_serializing_if = "Option::is_none")]
397    pub exclusive_maximum: Option<f64>,
398
399    /// The `minimum` keyword.
400    ///
401    /// See [JSON Schema Validation 6.2.4. "minimum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.4).
402    #[serde(skip_serializing_if = "Option::is_none")]
403    pub minimum: Option<f64>,
404
405    /// The `exclusiveMinimum` keyword.
406    ///
407    /// See [JSON Schema Validation 6.2.5. "exclusiveMinimum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.5).
408    #[serde(skip_serializing_if = "Option::is_none")]
409    pub exclusive_minimum: Option<f64>,
410}
411
412/// Properties of a [`SchemaObject`] which define validation assertions for strings.
413#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
414#[serde(rename_all = "camelCase", default)]
415pub struct StringValidation {
416    /// The `maxLength` keyword.
417    ///
418    /// See [JSON Schema Validation 6.3.1. "maxLength"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.1).
419    #[serde(skip_serializing_if = "Option::is_none")]
420    pub max_length: Option<u32>,
421
422    /// The `minLength` keyword.
423    ///
424    /// See [JSON Schema Validation 6.3.2. "minLength"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.2).
425    #[serde(skip_serializing_if = "Option::is_none")]
426    pub min_length: Option<u32>,
427
428    /// The `pattern` keyword.
429    ///
430    /// See [JSON Schema Validation 6.3.3. "pattern"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.3).
431    #[serde(skip_serializing_if = "Option::is_none")]
432    pub pattern: Option<String>,
433}
434
435/// Properties of a [`SchemaObject`] which define validation assertions for arrays.
436#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
437#[serde(rename_all = "camelCase", default)]
438pub struct ArrayValidation {
439    /// The `items` keyword.
440    ///
441    /// See [JSON Schema 9.3.1.1. "items"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.1).
442    #[serde(skip_serializing_if = "Option::is_none")]
443    pub items: Option<SingleOrVec<Schema>>,
444
445    /// The `additionalItems` keyword.
446    ///
447    /// See [JSON Schema 9.3.1.2. "additionalItems"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2).
448    #[serde(skip_serializing_if = "Option::is_none")]
449    pub additional_items: Option<Box<Schema>>,
450
451    /// The `unevaluatedItems` keyword.
452    ///
453    /// See [JSON Schema 9.3.1.3. "unevaluatedItems"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.3).
454    #[serde(skip_serializing_if = "Option::is_none")]
455    pub unevaluated_items: Option<Box<Schema>>,
456
457    /// The `maxItems` keyword.
458    ///
459    /// See [JSON Schema Validation 6.4.1. "maxItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.1).
460    #[serde(skip_serializing_if = "Option::is_none")]
461    pub max_items: Option<u32>,
462
463    /// The `minItems` keyword.
464    ///
465    /// See [JSON Schema Validation 6.4.2. "minItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.2).
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub min_items: Option<u32>,
468
469    /// The `uniqueItems` keyword.
470    ///
471    /// See [JSON Schema Validation 6.4.3. "uniqueItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.3).
472    #[serde(skip_serializing_if = "Option::is_none")]
473    pub unique_items: Option<bool>,
474
475    /// The `contains` keyword.
476    ///
477    /// See [JSON Schema 9.3.1.4. "contains"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.4).
478    #[serde(skip_serializing_if = "Option::is_none")]
479    pub contains: Option<Box<Schema>>,
480}
481
482/// Properties of a [`SchemaObject`] which define validation assertions for objects.
483#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
484#[serde(rename_all = "camelCase", default)]
485pub struct ObjectValidation {
486    /// The `maxProperties` keyword.
487    ///
488    /// See [JSON Schema Validation 6.5.1. "maxProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.1).
489    #[serde(skip_serializing_if = "Option::is_none")]
490    pub max_properties: Option<u32>,
491
492    /// The `minProperties` keyword.
493    ///
494    /// See [JSON Schema Validation 6.5.2. "minProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.2).
495    #[serde(skip_serializing_if = "Option::is_none")]
496    pub min_properties: Option<u32>,
497
498    /// The `required` keyword.
499    ///
500    /// See [JSON Schema Validation 6.5.3. "required"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.3).
501    #[serde(skip_serializing_if = "Set::is_empty")]
502    pub required: Set<String>,
503
504    /// The `properties` keyword.
505    ///
506    /// See [JSON Schema 9.3.2.1. "properties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1).
507    #[serde(skip_serializing_if = "Map::is_empty")]
508    pub properties: Map<String, Schema>,
509
510    /// The `patternProperties` keyword.
511    ///
512    /// See [JSON Schema 9.3.2.2. "patternProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.2).
513    #[serde(skip_serializing_if = "Map::is_empty")]
514    pub pattern_properties: Map<String, Schema>,
515
516    /// The `additionalProperties` keyword.
517    ///
518    /// See [JSON Schema 9.3.2.3. "additionalProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.3).
519    #[serde(skip_serializing_if = "is_none_or_default_true")]
520    pub additional_properties: Option<Box<Schema>>,
521
522    /// The `unevaluatedProperties` keyword.
523    ///
524    /// See [JSON Schema 9.3.2.4. "unevaluatedProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.4).
525    #[serde(skip_serializing_if = "is_none_or_default_true")]
526    pub unevaluated_properties: Option<Box<Schema>>,
527
528    /// The `propertyNames` keyword.
529    ///
530    /// See [JSON Schema 9.3.2.5. "propertyNames"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.5).
531    #[serde(skip_serializing_if = "Option::is_none")]
532    pub property_names: Option<Box<Schema>>,
533}
534
535/// The possible types of values in JSON Schema documents.
536///
537/// See [JSON Schema 4.2.1. Instance Data Model](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-4.2.1).
538#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
539#[serde(rename_all = "camelCase")]
540pub enum InstanceType {
541    Null,
542    Boolean,
543    Object,
544    Array,
545    Number,
546    String,
547    Integer,
548}
549
550/// A type which can be serialized as a single item, or multiple items.
551///
552/// In some contexts, a `Single` may be semantically distinct from a `Vec` containing only item.
553#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
554#[serde(untagged)]
555pub enum SingleOrVec<T> {
556    Single(Box<T>),
557    Vec(Vec<T>),
558}
559
560impl<T: Clone> Extend<T> for SingleOrVec<T> {
561    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
562        match self {
563            Self::Single(item) => {
564                *self = Self::Vec(iter::once(*item.clone()).chain(iter).collect());
565            }
566            Self::Vec(items) => items.extend(iter),
567        }
568    }
569}
570
571impl<'a, T> IntoIterator for &'a SingleOrVec<T> {
572    type Item = &'a T;
573
574    type IntoIter = std::slice::Iter<'a, T>;
575
576    fn into_iter(self) -> Self::IntoIter {
577        match self {
578            SingleOrVec::Single(item) => std::slice::from_ref(item.as_ref()).iter(),
579            SingleOrVec::Vec(items) => items.as_slice().iter(),
580        }
581    }
582}
583
584impl<T> From<T> for SingleOrVec<T> {
585    fn from(single: T) -> Self {
586        SingleOrVec::Single(Box::new(single))
587    }
588}
589
590impl<T> From<Vec<T>> for SingleOrVec<T> {
591    fn from(vec: Vec<T>) -> Self {
592        SingleOrVec::Vec(vec)
593    }
594}
595
596impl<T: PartialEq> SingleOrVec<T> {
597    /// Returns `true` if `self` is either a `Single` equal to `x`, or a `Vec` containing `x`.
598    pub fn contains(&self, x: &T) -> bool {
599        match self {
600            SingleOrVec::Single(s) => s.deref() == x,
601            SingleOrVec::Vec(v) => v.contains(x),
602        }
603    }
604}
605
606fn is_none_or_default_true(field: &Option<Box<Schema>>) -> bool {
607    match field {
608        None => true,
609        Some(value) => matches!(value.as_ref(), Schema::Bool(true)),
610    }
611}
612
613pub fn get_cleaned_schema_reference(schema_ref: &str) -> &str {
614    if let Some(cleaned) = schema_ref.strip_prefix(DEFINITIONS_PREFIX) {
615        cleaned
616    } else {
617        panic!(
618            "Tried to clean schema reference that does not start with the definition prefix: {schema_ref}"
619        );
620    }
621}