1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[allow(dead_code)]
8enum ElementPhase {
9 Annotation,
10 Type,
11 Identity,
12 Done,
13}
14
15pub struct ElementFrame {
17 phase: ElementPhase,
18 name: Option<NameId>,
19 ref_name: Option<QNameRef>,
20 target_namespace: Option<NameId>,
21 type_ref: Option<TypeRefResult>,
22 inline_type: Option<Box<TypeFrameResult>>,
23 substitution_group: Vec<QNameRef>,
24 default_value: Option<String>,
25 fixed_value: Option<String>,
26 nillable: bool,
27 is_abstract: bool,
28 min_occurs: u32,
29 max_occurs: Option<u32>,
30 block: Option<DerivationSet>,
31 final_derivation: Option<DerivationSet>,
32 form: Option<String>,
33 id: Option<String>,
34 alternatives: Vec<AlternativeResult>,
35 identity_constraints: Vec<IdentityResult>,
36 identity_constraint_refs: Vec<IdentityRefResult>,
38 annotation: Option<Annotation>,
39 source: Option<SourceRef>,
40 foreign_attributes: Vec<ForeignAttribute>,
41}
42
43impl ElementFrame {
44 pub fn new(
45 attrs: &AttributeMap,
46 name_table: &NameTable,
47 source: Option<SourceRef>,
48 ns_snapshot: &NamespaceContextSnapshot,
49 ) -> SchemaResult<Self> {
50 let name = attrs
51 .get_value_by_name(name_table, "name")
52 .and_then(|s| name_table.get(s));
53
54 let ref_name = attrs
55 .get_value_by_name(name_table, "ref")
56 .map(|s| parse_qname_ref(s, name_table, ns_snapshot))
57 .transpose()?;
58
59 let target_namespace = attrs
60 .get_value_by_name(name_table, "targetNamespace")
61 .map(|s| name_table.add(s));
62
63 let type_ref = attrs
64 .get_value_by_name(name_table, "type")
65 .map(|s| parse_qname_ref(s, name_table, ns_snapshot))
66 .transpose()?
67 .map(TypeRefResult::QName);
68
69 let substitution_group = attrs
70 .get_value_by_name(name_table, "substitutionGroup")
71 .map(|s| parse_qname_list(s, name_table, ns_snapshot))
72 .transpose()?
73 .unwrap_or_default();
74
75 let default_value = attrs
76 .get_value_by_name(name_table, "default")
77 .map(String::from);
78
79 let fixed_value = attrs
80 .get_value_by_name(name_table, "fixed")
81 .map(String::from);
82
83 let nillable = parse_bool_attr_default(attrs, name_table, "nillable", false)?;
84
85 let is_abstract = parse_bool_attr_default(attrs, name_table, "abstract", false)?;
86
87 let min_occurs = parse_min_occurs_attr(attrs, name_table, "minOccurs")?;
88
89 let max_occurs = parse_max_occurs_attr(attrs, name_table, "maxOccurs")?;
90
91 let block = parse_derivation_set_opt(
92 attrs.get_value_by_name(name_table, "block"),
93 )?;
94
95 let final_derivation = parse_derivation_set_opt(
96 attrs.get_value_by_name(name_table, "final"),
97 )?;
98
99 let form = attrs
100 .get_value_by_name(name_table, "form")
101 .map(String::from);
102
103 let id = attrs
104 .get_value_by_name(name_table, "id")
105 .map(String::from);
106
107 Ok(Self {
108 phase: ElementPhase::Annotation,
109 name,
110 ref_name,
111 target_namespace,
112 type_ref,
113 inline_type: None,
114 substitution_group,
115 default_value,
116 fixed_value,
117 nillable,
118 is_abstract,
119 min_occurs,
120 max_occurs,
121 block,
122 final_derivation,
123 form,
124 id,
125 alternatives: Vec::new(),
126 identity_constraints: Vec::new(),
127 identity_constraint_refs: Vec::new(),
128 annotation: None,
129 source,
130 foreign_attributes: Vec::new(),
131 })
132 }
133}
134
135impl Frame for ElementFrame {
136 fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
137 #[cfg(feature = "xsd11")]
138 let is_xsd11_element = matches!(local_name, xsd_names::ALTERNATIVE);
139 #[cfg(not(feature = "xsd11"))]
140 let is_xsd11_element = false;
141
142 if self.ref_name.is_some() {
145 return local_name == xsd_names::ANNOTATION
146 && self.phase == ElementPhase::Annotation;
147 }
148
149 match self.phase {
150 ElementPhase::Annotation => matches!(
151 local_name,
152 xsd_names::ANNOTATION
153 | xsd_names::SIMPLE_TYPE
154 | xsd_names::COMPLEX_TYPE
155 | xsd_names::KEY
156 | xsd_names::KEYREF
157 | xsd_names::UNIQUE
158 ) || is_xsd11_element,
159 ElementPhase::Type => matches!(
160 local_name,
161 xsd_names::SIMPLE_TYPE
162 | xsd_names::COMPLEX_TYPE
163 | xsd_names::KEY
164 | xsd_names::KEYREF
165 | xsd_names::UNIQUE
166 ) || is_xsd11_element,
167 ElementPhase::Identity => {
168 matches!(
169 local_name,
170 xsd_names::KEY | xsd_names::KEYREF | xsd_names::UNIQUE
171 ) || is_xsd11_element
172 }
173 ElementPhase::Done => false,
174 }
175 }
176
177 fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
178 matches!(
179 local_name,
180 "name"
181 | "ref"
182 | "targetNamespace"
183 | "type"
184 | "substitutionGroup"
185 | "default"
186 | "fixed"
187 | "nillable"
188 | "abstract"
189 | "minOccurs"
190 | "maxOccurs"
191 | "block"
192 | "final"
193 | "form"
194 | "id"
195 )
196 }
197
198 fn on_child_start(&mut self, local_name: &str, _name_table: &NameTable) {
199 match local_name {
200 xsd_names::ANNOTATION => {
201 self.phase = ElementPhase::Type;
202 }
203 xsd_names::SIMPLE_TYPE | xsd_names::COMPLEX_TYPE => {
204 self.phase = ElementPhase::Identity;
205 }
206 xsd_names::ALTERNATIVE => {
207 self.phase = ElementPhase::Identity;
208 }
209 xsd_names::KEY | xsd_names::KEYREF | xsd_names::UNIQUE => {
210 self.phase = ElementPhase::Identity;
211 }
212 _ => {}
213 }
214 }
215
216 fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
217 match child {
218 FrameResult::Annotation(ann) => {
219 self.annotation = Some(ann);
220 }
221 FrameResult::Type(t) => {
222 self.inline_type = Some(Box::new(t));
223 }
224 FrameResult::Alternative(alt) => {
225 self.alternatives.push(alt);
226 }
227 FrameResult::Identity(ic) => {
228 self.identity_constraints.push(ic);
229 }
230 FrameResult::IdentityRef(ic_ref) => {
231 self.identity_constraint_refs.push(ic_ref);
232 }
233 FrameResult::Skip => {}
234 _ => {}
235 }
236 Ok(())
237 }
238
239 fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
240 if self.type_ref.is_some() && self.inline_type.is_some() {
242 return Err(SchemaError::structural(
243 "src-element",
244 "Element cannot have both 'type' attribute and inline type definition",
245 None,
246 ));
247 }
248
249 let annotation = merge_foreign_attributes(
250 self.annotation,
251 self.foreign_attributes,
252 self.source.clone(),
253 );
254 Ok(FrameResult::Element(ElementFrameResult {
255 name: self.name,
256 ref_name: self.ref_name,
257 target_namespace: self.target_namespace,
258 type_ref: self.type_ref,
259 inline_type: self.inline_type,
260 substitution_group: self.substitution_group,
261 default_value: self.default_value,
262 fixed_value: self.fixed_value,
263 nillable: self.nillable,
264 is_abstract: self.is_abstract,
265 min_occurs: self.min_occurs,
266 max_occurs: self.max_occurs,
267 block: self.block,
268 final_derivation: self.final_derivation,
269 form: self.form,
270 id: self.id,
271 alternatives: self.alternatives,
272 identity_constraints: self.identity_constraints,
273 identity_constraint_refs: self.identity_constraint_refs,
274 annotation,
275 source: self.source,
276 }))
277 }
278
279 fn has_annotation(&self) -> bool {
280 self.annotation.is_some()
281 }
282
283 fn source(&self) -> Option<&SourceRef> {
284 self.source.as_ref()
285 }
286
287 fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>) {
288 self.foreign_attributes = attrs;
289 }
290}
291
292pub struct AttributeFrame {
298 name: Option<NameId>,
299 ref_name: Option<QNameRef>,
300 target_namespace: Option<NameId>,
301 type_ref: Option<TypeRefResult>,
302 inline_type: Option<Box<SimpleTypeResult>>,
303 default_value: Option<String>,
304 fixed_value: Option<String>,
305 use_kind: Option<String>,
306 form: Option<String>,
307 inheritable: bool,
308 id: Option<String>,
309 annotation: Option<Annotation>,
310 past_annotation: bool,
312 source: Option<SourceRef>,
313 foreign_attributes: Vec<ForeignAttribute>,
314}
315
316impl AttributeFrame {
317 pub fn new(
318 attrs: &AttributeMap,
319 name_table: &NameTable,
320 source: Option<SourceRef>,
321 ns_snapshot: &NamespaceContextSnapshot,
322 ) -> SchemaResult<Self> {
323 let name = attrs
324 .get_value_by_name(name_table, "name")
325 .and_then(|s| name_table.get(s));
326
327 let ref_name = attrs
328 .get_value_by_name(name_table, "ref")
329 .map(|s| parse_qname_ref(s, name_table, ns_snapshot))
330 .transpose()?;
331
332 let target_namespace = attrs
333 .get_value_by_name(name_table, "targetNamespace")
334 .map(|s| name_table.add(s));
335
336 let type_ref = attrs
337 .get_value_by_name(name_table, "type")
338 .map(|s| parse_qname_ref(s, name_table, ns_snapshot))
339 .transpose()?
340 .map(TypeRefResult::QName);
341
342 let default_value = attrs
343 .get_value_by_name(name_table, "default")
344 .map(String::from);
345
346 let fixed_value = attrs
347 .get_value_by_name(name_table, "fixed")
348 .map(String::from);
349
350 validate_attr_value(attrs, name_table, "use", parse_use)?;
351 let use_kind = attrs
352 .get_value_by_name(name_table, "use")
353 .map(String::from);
354
355 validate_attr_value(attrs, name_table, "form", parse_form)?;
356 let form = attrs
357 .get_value_by_name(name_table, "form")
358 .map(String::from);
359
360 let inheritable = parse_bool_attr_default(attrs, name_table, "inheritable", false)?;
361
362 let id = attrs
363 .get_value_by_name(name_table, "id")
364 .map(String::from);
365
366 Ok(Self {
367 name,
368 ref_name,
369 target_namespace,
370 type_ref,
371 inline_type: None,
372 default_value,
373 fixed_value,
374 use_kind,
375 form,
376 inheritable,
377 id,
378 annotation: None,
379 past_annotation: false,
380 source,
381 foreign_attributes: Vec::new(),
382 })
383 }
384}
385
386impl Frame for AttributeFrame {
387 fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
388 if local_name == xsd_names::ANNOTATION && self.past_annotation {
392 return false;
393 }
394 if local_name == xsd_names::SIMPLE_TYPE && self.inline_type.is_some() {
395 return false;
396 }
397 matches!(local_name, xsd_names::ANNOTATION | xsd_names::SIMPLE_TYPE)
398 }
399
400 fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
401 matches!(
402 local_name,
403 "name"
404 | "ref"
405 | "targetNamespace"
406 | "type"
407 | "default"
408 | "fixed"
409 | "use"
410 | "form"
411 | "inheritable"
412 | "id"
413 )
414 }
415
416 fn on_child_start(&mut self, local_name: &str, _name_table: &NameTable) {
417 if local_name != xsd_names::ANNOTATION {
418 self.past_annotation = true;
419 }
420 }
421
422 fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
423 match child {
424 FrameResult::Annotation(ann) => {
425 self.annotation = Some(ann);
426 }
427 FrameResult::Type(TypeFrameResult::Simple(st)) => {
428 self.inline_type = Some(st);
429 }
430 FrameResult::Skip => {}
431 _ => {}
432 }
433 Ok(())
434 }
435
436 fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
437 if self.ref_name.is_some() && self.inline_type.is_some() {
439 return Err(SchemaError::structural(
440 "src-attribute",
441 "Attribute reference cannot have inline simpleType",
442 None,
443 ));
444 }
445 if self.type_ref.is_some() && self.inline_type.is_some() {
447 return Err(SchemaError::structural(
448 "src-attribute",
449 "Attribute cannot have both 'type' attribute and inline simpleType",
450 None,
451 ));
452 }
453
454 let annotation = merge_foreign_attributes(
455 self.annotation,
456 self.foreign_attributes,
457 self.source.clone(),
458 );
459 Ok(FrameResult::Attribute(AttributeFrameResult {
460 name: self.name,
461 ref_name: self.ref_name,
462 target_namespace: self.target_namespace,
463 type_ref: self.type_ref,
464 inline_type: self.inline_type,
465 default_value: self.default_value,
466 fixed_value: self.fixed_value,
467 use_kind: self.use_kind,
468 form: self.form,
469 inheritable: self.inheritable,
470 id: self.id,
471 annotation,
472 source: self.source,
473 }))
474 }
475
476 fn has_annotation(&self) -> bool {
477 self.annotation.is_some()
478 }
479
480 fn source(&self) -> Option<&SourceRef> {
481 self.source.as_ref()
482 }
483
484 fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>) {
485 self.foreign_attributes = attrs;
486 }
487}
488