schemars/
schema.rs

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