1use std::hash::{Hash, Hasher};
4use std::ops::{Deref, DerefMut};
5
6use crate::models::{
7 schema::{
8 xs::{
9 FormChoiceType, NamespaceListType, NotNamespaceType, ProcessContentsType, QnameListType,
10 },
11 MaxOccurs, MinOccurs,
12 },
13 ElementIdent, TypeIdent,
14};
15
16use super::{MetaTypes, TypeEq};
17
18#[derive(Debug, Clone)]
20pub struct ElementMeta {
21 pub ident: ElementIdent,
23
24 pub variant: ElementMetaVariant,
26
27 pub form: FormChoiceType,
29
30 pub nillable: bool,
32
33 pub min_occurs: MinOccurs,
35
36 pub max_occurs: MaxOccurs,
38
39 pub display_name: Option<String>,
41
42 pub documentation: Vec<String>,
44}
45
46#[derive(Debug, Clone)]
50pub enum ElementMetaVariant {
51 Text,
53
54 Any {
56 meta: AnyMeta,
58 },
59
60 Type {
62 type_: TypeIdent,
64
65 mode: ElementMode,
67 },
68}
69
70#[allow(missing_docs)]
73#[derive(Debug, Clone, Eq, PartialEq)]
74pub struct AnyMeta {
75 pub id: Option<String>,
76 pub namespace: Option<NamespaceListType>,
77 pub not_q_name: Option<QnameListType>,
78 pub not_namespace: Option<NotNamespaceType>,
79 pub process_contents: ProcessContentsType,
80}
81
82#[derive(Default, Debug, Clone)]
84pub struct ElementsMeta(pub Vec<ElementMeta>);
85
86#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
88pub enum ElementMode {
89 Element,
91
92 Group,
94}
95
96impl ElementMeta {
99 #[must_use]
102 pub fn new(
103 ident: ElementIdent,
104 type_: TypeIdent,
105 mode: ElementMode,
106 form: FormChoiceType,
107 ) -> Self {
108 Self {
109 ident,
110 variant: ElementMetaVariant::Type { type_, mode },
111 form,
112 nillable: false,
113 min_occurs: 1,
114 max_occurs: MaxOccurs::Bounded(1),
115 display_name: None,
116 documentation: Vec::new(),
117 }
118 }
119
120 #[must_use]
122 pub fn any(ident: ElementIdent, meta: AnyMeta) -> Self {
123 Self {
124 ident,
125 variant: ElementMetaVariant::Any { meta },
126 form: FormChoiceType::Unqualified,
127 nillable: false,
128 min_occurs: 1,
129 max_occurs: MaxOccurs::Bounded(1),
130 display_name: None,
131 documentation: Vec::new(),
132 }
133 }
134
135 #[must_use]
137 pub fn text(ident: ElementIdent) -> Self {
138 Self {
139 ident,
140 variant: ElementMetaVariant::Text,
141 form: FormChoiceType::Unqualified,
142 nillable: false,
143 min_occurs: 1,
144 max_occurs: MaxOccurs::Bounded(1),
145 display_name: None,
146 documentation: Vec::new(),
147 }
148 }
149
150 #[must_use]
152 pub fn is_text(&self) -> bool {
153 matches!(&self.variant, ElementMetaVariant::Text)
154 }
155
156 #[must_use]
158 pub fn is_any(&self) -> bool {
159 matches!(&self.variant, ElementMetaVariant::Any { .. })
160 }
161
162 #[must_use]
164 pub fn as_any(&self) -> Option<&AnyMeta> {
165 if let ElementMetaVariant::Any { meta } = &self.variant {
166 Some(meta)
167 } else {
168 None
169 }
170 }
171}
172
173impl TypeEq for ElementMeta {
174 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &MetaTypes) {
175 let Self {
176 ident,
177 variant,
178 form,
179 nillable,
180 min_occurs,
181 max_occurs,
182 display_name,
183 documentation,
184 } = self;
185
186 ident.hash(hasher);
187 variant.type_hash(hasher, types);
188 form.hash(hasher);
189 nillable.hash(hasher);
190 min_occurs.hash(hasher);
191 max_occurs.hash(hasher);
192 display_name.hash(hasher);
193 documentation.hash(hasher);
194 }
195
196 fn type_eq(&self, other: &Self, types: &MetaTypes) -> bool {
197 let Self {
198 ident,
199 variant,
200 form,
201 nillable,
202 min_occurs,
203 max_occurs,
204 display_name,
205 documentation,
206 } = self;
207
208 ident.eq(&other.ident)
209 && variant.type_eq(&other.variant, types)
210 && form.eq(&other.form)
211 && nillable.eq(&other.nillable)
212 && min_occurs.eq(&other.min_occurs)
213 && max_occurs.eq(&other.max_occurs)
214 && display_name.eq(&other.display_name)
215 && documentation.eq(&other.documentation)
216 }
217}
218
219impl ElementsMeta {
222 pub fn push_any(&mut self, mut el: ElementMeta) {
227 let mut i = 0;
228 for element in &mut self.0 {
229 if element.is_any() && element.ident.name.is_generated() {
230 element.display_name = Some(format!("any_{i}"));
231 i += 1;
232 }
233 }
234
235 el.display_name = Some(if i > 0 {
236 format!("any_{i}")
237 } else {
238 "any".into()
239 });
240
241 self.0.push(el);
242 }
243}
244
245impl Deref for ElementsMeta {
246 type Target = Vec<ElementMeta>;
247
248 fn deref(&self) -> &Self::Target {
249 &self.0
250 }
251}
252
253impl DerefMut for ElementsMeta {
254 fn deref_mut(&mut self) -> &mut Self::Target {
255 &mut self.0
256 }
257}
258
259impl TypeEq for ElementsMeta {
260 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &MetaTypes) {
261 TypeEq::type_hash_slice(&self.0, hasher, types);
262 }
263
264 fn type_eq(&self, other: &Self, types: &MetaTypes) -> bool {
265 TypeEq::type_eq_iter(self.0.iter(), other.0.iter(), types)
266 }
267}
268
269impl TypeEq for ElementMetaVariant {
272 fn type_hash<H: Hasher>(&self, hasher: &mut H, types: &MetaTypes) {
273 match self {
274 Self::Any { meta } => {
275 hasher.write_u8(0);
276 meta.hash(hasher);
277 }
278 Self::Type { type_, mode } => {
279 hasher.write_u8(1);
280 type_.type_hash(hasher, types);
281 mode.hash(hasher);
282 }
283 Self::Text => hasher.write_u8(2),
284 }
285 }
286
287 fn type_eq(&self, other: &Self, types: &MetaTypes) -> bool {
288 match (self, other) {
289 (Self::Any { meta: a }, Self::Any { meta: b }) => a.eq(b),
290 (
291 Self::Type {
292 type_: type_a,
293 mode: mode_a,
294 },
295 Self::Type {
296 type_: type_b,
297 mode: mode_b,
298 },
299 ) => mode_a.eq(mode_b) && type_a.type_eq(type_b, types),
300 (_, _) => false,
301 }
302 }
303}
304
305impl Hash for AnyMeta {
308 fn hash<H: Hasher>(&self, hasher: &mut H) {
309 self.id.hash(hasher);
313 }
314}