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}