jsonschema_schema/schema/
add.rs1use alloc::collections::BTreeMap;
2use core::ops::Add;
3
4use indexmap::IndexMap;
5
6use crate::extensions::IntellijSchemaExt;
7use crate::extensions::TombiSchemaExt;
8
9use super::Schema;
10
11fn merge_index_map<V>(
14 mut target: IndexMap<String, V>,
15 source: IndexMap<String, V>,
16) -> IndexMap<String, V> {
17 for (k, v) in source {
18 target.entry(k).or_insert(v);
19 }
20 target
21}
22
23fn merge_option_btree_map<V>(
26 target: Option<BTreeMap<String, V>>,
27 source: Option<BTreeMap<String, V>>,
28) -> Option<BTreeMap<String, V>> {
29 match (target, source) {
30 (Some(mut t), Some(s)) => {
31 for (k, v) in s {
32 t.entry(k).or_insert(v);
33 }
34 Some(t)
35 }
36 (t, s) => t.or(s),
37 }
38}
39
40fn union_option_vec(
42 target: Option<Vec<String>>,
43 source: Option<Vec<String>>,
44) -> Option<Vec<String>> {
45 match (target, source) {
46 (Some(mut t), Some(s)) => {
47 for item in s {
48 if !t.contains(&item) {
49 t.push(item);
50 }
51 }
52 Some(t)
53 }
54 (t, s) => t.or(s),
55 }
56}
57
58impl Add for Schema {
59 type Output = Self;
60
61 #[allow(clippy::too_many_lines)]
70 fn add(self, rhs: Self) -> Self {
71 let extra = {
72 let mut merged = self.extra;
73 for (k, v) in rhs.extra {
74 merged.entry(k).or_insert(v);
75 }
76 merged
77 };
78
79 let x_tombi = TombiSchemaExt {
80 toml_version: self.x_tombi.toml_version.or(rhs.x_tombi.toml_version),
81 table_keys_order: self
82 .x_tombi
83 .table_keys_order
84 .or(rhs.x_tombi.table_keys_order),
85 additional_key_label: self
86 .x_tombi
87 .additional_key_label
88 .or(rhs.x_tombi.additional_key_label),
89 array_values_order: self
90 .x_tombi
91 .array_values_order
92 .or(rhs.x_tombi.array_values_order),
93 };
94
95 Self {
96 schema: self.schema.or(rhs.schema),
98 id: self.id.or(rhs.id),
99 ref_: self.ref_.or(rhs.ref_),
100 anchor: self.anchor.or(rhs.anchor),
101 dynamic_ref: self.dynamic_ref.or(rhs.dynamic_ref),
102 dynamic_anchor: self.dynamic_anchor.or(rhs.dynamic_anchor),
103 comment: self.comment.or(rhs.comment),
104 defs: merge_option_btree_map(self.defs, rhs.defs),
105 vocabulary: self.vocabulary.or(rhs.vocabulary),
106
107 title: self.title.or(rhs.title),
109 description: self.description.or(rhs.description),
110 default: self.default.or(rhs.default),
111 deprecated: self.deprecated || rhs.deprecated,
112 read_only: self.read_only || rhs.read_only,
113 write_only: self.write_only || rhs.write_only,
114 examples: self.examples.or(rhs.examples),
115
116 type_: self.type_.or(rhs.type_),
118 enum_: self.enum_.or(rhs.enum_),
119 markdown_enum_descriptions: self
120 .markdown_enum_descriptions
121 .or(rhs.markdown_enum_descriptions),
122 const_: self.const_.or(rhs.const_),
123
124 properties: merge_index_map(self.properties, rhs.properties),
126 pattern_properties: merge_index_map(self.pattern_properties, rhs.pattern_properties),
127 additional_properties: self.additional_properties.or(rhs.additional_properties),
128 required: union_option_vec(self.required, rhs.required),
129 property_names: self.property_names.or(rhs.property_names),
130 min_properties: self.min_properties.or(rhs.min_properties),
131 max_properties: self.max_properties.or(rhs.max_properties),
132 unevaluated_properties: self.unevaluated_properties.or(rhs.unevaluated_properties),
133
134 items: self.items.or(rhs.items),
136 prefix_items: self.prefix_items.or(rhs.prefix_items),
137 contains: self.contains.or(rhs.contains),
138 min_contains: self.min_contains.or(rhs.min_contains),
139 max_contains: self.max_contains.or(rhs.max_contains),
140 min_items: self.min_items.or(rhs.min_items),
141 max_items: self.max_items.or(rhs.max_items),
142 unique_items: self.unique_items || rhs.unique_items,
143 unevaluated_items: self.unevaluated_items.or(rhs.unevaluated_items),
144
145 minimum: self.minimum.or(rhs.minimum),
147 maximum: self.maximum.or(rhs.maximum),
148 exclusive_minimum: self.exclusive_minimum.or(rhs.exclusive_minimum),
149 exclusive_maximum: self.exclusive_maximum.or(rhs.exclusive_maximum),
150 multiple_of: self.multiple_of.or(rhs.multiple_of),
151
152 min_length: self.min_length.or(rhs.min_length),
154 max_length: self.max_length.or(rhs.max_length),
155 pattern: self.pattern.or(rhs.pattern),
156 format: self.format.or(rhs.format),
157
158 all_of: self.all_of.or(rhs.all_of),
160 any_of: self.any_of.or(rhs.any_of),
161 one_of: self.one_of.or(rhs.one_of),
162 not: self.not.or(rhs.not),
163
164 if_: self.if_.or(rhs.if_),
166 then_: self.then_.or(rhs.then_),
167 else_: self.else_.or(rhs.else_),
168
169 dependent_required: self.dependent_required.or(rhs.dependent_required),
171 dependent_schemas: merge_index_map(self.dependent_schemas, rhs.dependent_schemas),
172
173 content_media_type: self.content_media_type.or(rhs.content_media_type),
175 content_encoding: self.content_encoding.or(rhs.content_encoding),
176 content_schema: self.content_schema.or(rhs.content_schema),
177
178 markdown_description: self.markdown_description.or(rhs.markdown_description),
180 x_lintel: self.x_lintel.or(rhs.x_lintel),
181 x_taplo: self.x_taplo.or(rhs.x_taplo),
182 x_taplo_info: self.x_taplo_info.or(rhs.x_taplo_info),
183 x_tombi,
184 x_intellij: IntellijSchemaExt {
185 html_description: self
186 .x_intellij
187 .html_description
188 .or(rhs.x_intellij.html_description),
189 language_injection: self
190 .x_intellij
191 .language_injection
192 .or(rhs.x_intellij.language_injection),
193 enum_metadata: self
194 .x_intellij
195 .enum_metadata
196 .or(rhs.x_intellij.enum_metadata),
197 },
198
199 extra,
200 }
201 }
202}