vector_config_common/schema/
json_schema.rs

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