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}