tamasfe_schemars/
flatten.rs1use crate::schema::*;
2use crate::{Map, Set};
3
4impl Schema {
5 #[doc(hidden)]
6 pub fn flatten(self, other: Self) -> Schema {
7 if is_null_type(&self) {
8 return other;
9 } else if is_null_type(&other) {
10 return self;
11 }
12 let s1: SchemaObject = self.into();
13 let s2: SchemaObject = other.into();
14 Schema::Object(s1.merge(s2))
15 }
16}
17
18pub(crate) trait Merge: Sized {
19 fn merge(self, other: Self) -> Self;
20}
21
22macro_rules! impl_merge {
23 ($ty:ident { merge: $($merge_field:ident)*, or: $($or_field:ident)*, }) => {
24 impl Merge for $ty {
25 fn merge(self, other: Self) -> Self {
26 $ty {
27 $($merge_field: self.$merge_field.merge(other.$merge_field),)*
28 $($or_field: self.$or_field.or(other.$or_field),)*
29 }
30 }
31 }
32 };
33 ($ty:ident { or: $($or_field:ident)*, }) => {
34 impl_merge!( $ty { merge: , or: $($or_field)*, });
35 };
36}
37
38impl_merge!(SchemaObject {
39 merge: extensions instance_type enum_values
40 metadata subschemas number string array object,
41 or: format const_value reference,
42});
43
44impl Merge for Metadata {
45 fn merge(self, other: Self) -> Self {
46 Metadata {
47 id: self.id.or(other.id),
48 title: self.title.or(other.title),
49 description: self.description.or(other.description),
50 default: self.default.or(other.default),
51 deprecated: self.deprecated || other.deprecated,
52 read_only: self.read_only || other.read_only,
53 write_only: self.write_only || other.write_only,
54 examples: self.examples.merge(other.examples),
55 }
56 }
57}
58
59impl_merge!(SubschemaValidation {
60 or: all_of any_of one_of not if_schema then_schema else_schema,
61});
62
63impl_merge!(NumberValidation {
64 or: multiple_of maximum exclusive_maximum minimum exclusive_minimum,
65});
66
67impl_merge!(StringValidation {
68 or: max_length min_length pattern,
69});
70
71impl_merge!(ArrayValidation {
72 or: items additional_items max_items min_items unique_items contains,
73});
74
75impl_merge!(ObjectValidation {
76 merge: required properties pattern_properties,
77 or: max_properties min_properties additional_properties property_names,
78});
79
80impl<T: Merge> Merge for Option<T> {
81 fn merge(self, other: Self) -> Self {
82 match (self, other) {
83 (Some(x), Some(y)) => Some(x.merge(y)),
84 (None, y) => y,
85 (x, None) => x,
86 }
87 }
88}
89
90impl<T: Merge> Merge for Box<T> {
91 fn merge(mut self, other: Self) -> Self {
92 *self = (*self).merge(*other);
93 self
94 }
95}
96
97impl<T> Merge for Vec<T> {
98 fn merge(mut self, other: Self) -> Self {
99 self.extend(other);
100 self
101 }
102}
103
104impl<K, V> Merge for Map<K, V>
105where
106 K: std::hash::Hash + Eq + Ord,
107{
108 fn merge(mut self, other: Self) -> Self {
109 self.extend(other);
110 self
111 }
112}
113
114impl<T: Ord> Merge for Set<T> {
115 fn merge(mut self, other: Self) -> Self {
116 self.extend(other);
117 self
118 }
119}
120
121impl Merge for SingleOrVec<InstanceType> {
122 fn merge(self, other: Self) -> Self {
123 if self == other {
124 return self;
125 }
126 let mut vec = match (self, other) {
127 (SingleOrVec::Vec(v1), SingleOrVec::Vec(v2)) => v1.merge(v2),
128 (SingleOrVec::Vec(mut v), SingleOrVec::Single(s))
129 | (SingleOrVec::Single(s), SingleOrVec::Vec(mut v)) => {
130 v.push(*s);
131 v
132 }
133 (SingleOrVec::Single(s1), SingleOrVec::Single(s2)) => vec![*s1, *s2],
134 };
135 vec.sort();
136 vec.dedup();
137 SingleOrVec::Vec(vec)
138 }
139}
140
141fn is_null_type(schema: &Schema) -> bool {
142 let s = match schema {
143 Schema::Object(s) => s,
144 _ => return false,
145 };
146 match &s.instance_type {
147 Some(SingleOrVec::Single(t)) if **t == InstanceType::Null => true,
148 _ => false,
149 }
150}