1use std::cell::RefCell;
2use std::collections::{
3 btree_map::Entry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet,
4};
5use std::mem::replace;
6use std::ops::Not;
7use std::rc::Rc;
8
9use proc_macro2::{Ident as Ident2, TokenStream};
10use quote::{format_ident, quote};
11
12use xsd_parser_types::misc::Namespace;
13
14use crate::config::{GeneratorFlags, TypedefMode};
15use crate::models::{
16 code::IdentPath,
17 data::{
18 ComplexBase, ComplexData, ComplexDataAttribute, ComplexDataContent, ComplexDataElement,
19 ComplexDataEnum, ComplexDataStruct, DataTypeVariant, DynamicData, EnumerationData,
20 EnumerationDataVariant, EnumerationVariantValue, Occurs, PathData, ReferenceData,
21 SimpleData, TagName, UnionData, UnionTypeVariant,
22 },
23 meta::{CustomMetaNamespace, ElementMetaVariant, MetaTypeVariant, MetaTypes},
24 schema::{xs::FormChoiceType, NamespaceId},
25 TypeIdent,
26};
27
28use super::super::super::{
29 context::{Context, ValueKey},
30 MetaData, RenderStep, RenderStepType,
31};
32
33#[derive(Debug, Clone)]
35pub struct QuickXmlSerializeRenderStep {
36 pub namespaces: NamespaceSerialization,
38
39 pub default_namespace: Option<Namespace>,
41}
42
43#[derive(Debug, Clone, Copy, Eq, PartialEq)]
46pub enum NamespaceSerialization {
47 None,
49
50 Local,
53
54 Global,
56
57 Dynamic,
66}
67
68impl NamespaceSerialization {
69 #[inline]
71 #[must_use]
72 pub fn is_none(&self) -> bool {
73 matches!(self, Self::None)
74 }
75
76 #[inline]
80 #[must_use]
81 pub fn is_some(&self) -> bool {
82 matches!(self, Self::Local | Self::Global | Self::Dynamic)
83 }
84}
85
86macro_rules! resolve_build_in {
87 ($ctx:ident, $path:expr) => {
88 $ctx.resolve_build_in($path)
89 };
90}
91
92macro_rules! resolve_ident {
93 ($ctx:ident, $path:expr) => {
94 $ctx.resolve_ident_path($path)
95 };
96}
97
98macro_rules! resolve_quick_xml_ident {
99 ($ctx:ident, $path:expr) => {
100 $ctx.resolve_quick_xml_serialize_ident_path($path)
101 };
102}
103
104struct SerializerConfig;
105
106impl ValueKey for SerializerConfig {
107 type Type = QuickXmlSerializeRenderStep;
108}
109
110#[derive(Default, Debug)]
111struct NamespaceCollector {
112 cache: HashMap<TypeIdent, Option<SharedGlobalNamespaces>>,
113 xsi_namespace: Option<NamespaceId>,
114 nillable_type_support: bool,
115}
116
117#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
118enum NamespaceKey {
119 Normal(NamespaceId),
120 Default(NamespaceId),
121}
122
123type GlobalNamespaces = BTreeMap<NamespaceKey, (Option<PathData>, PathData)>;
124type SharedGlobalNamespaces = Rc<GlobalNamespaces>;
125
126impl RenderStep for QuickXmlSerializeRenderStep {
127 fn render_step_type(&self) -> RenderStepType {
128 RenderStepType::ExtraImpls
129 }
130
131 fn initialize(&mut self, meta: &mut MetaData<'_>) {
132 let ident = IdentPath::from_parts(
133 [meta.xsd_parser_types.clone(), format_ident!("quick_xml")],
134 format_ident!("WithBoxedSerializer"),
135 );
136
137 if !meta.dyn_type_traits.contains(&ident) {
138 meta.dyn_type_traits.push(ident);
139 }
140 }
141
142 fn render_type(&mut self, ctx: &mut Context<'_, '_>) {
143 ctx.set::<SerializerConfig>(self.clone());
144
145 match &ctx.data.variant {
146 DataTypeVariant::BuildIn(_) | DataTypeVariant::Custom(_) => (),
147 DataTypeVariant::Union(x) => x.render_serializer(ctx),
148 DataTypeVariant::Dynamic(x) => x.render_serializer(ctx),
149 DataTypeVariant::Reference(x) => x.render_serializer(ctx),
150 DataTypeVariant::Enumeration(x) => x.render_serializer(ctx),
151 DataTypeVariant::Simple(x) => x.render_serializer(ctx),
152 DataTypeVariant::Complex(x) => x.render_serializer(ctx),
153 }
154
155 ctx.unset::<SerializerConfig>();
156 }
157}
158
159impl UnionData<'_> {
162 pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
163 let Self {
164 type_ident,
165 variants,
166 ..
167 } = self;
168
169 let variants = variants
170 .iter()
171 .map(UnionTypeVariant::render_serializer_variant)
172 .collect::<Vec<_>>();
173
174 let str_ = resolve_build_in!(ctx, "::core::primitive::str");
175 let result = resolve_build_in!(ctx, "::core::result::Result");
176 let option = resolve_build_in!(ctx, "::core::option::Option");
177
178 let cow = resolve_ident!(ctx, "::alloc::borrow::Cow");
179 let error = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::Error");
180 let serialize_bytes = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeBytes");
181 let serialize_helper =
182 resolve_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeHelper");
183 let with_serializer_to_bytes =
184 resolve_ident!(ctx, "xsd_parser_types::quick_xml::WithSerializeToBytes");
185
186 let code = quote! {
187 impl #serialize_bytes for #type_ident {
188 fn serialize_bytes(&self, helper: &mut #serialize_helper) -> #result<#option<#cow<'_, #str_>>, #error> {
189 match self {
190 #( #variants )*
191 }
192 }
193 }
194 impl #with_serializer_to_bytes for #type_ident { }
195 };
196
197 ctx.current_module().append(code);
198 }
199}
200
201impl UnionTypeVariant<'_> {
202 fn render_serializer_variant(&self) -> TokenStream {
203 let Self { variant_ident, .. } = self;
204
205 quote! {
206 Self::#variant_ident(x) => x.serialize_bytes(helper),
207 }
208 }
209}
210
211impl DynamicData<'_> {
214 pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
215 let Self { type_ident, .. } = self;
216
217 let str_ = resolve_build_in!(ctx, "::core::primitive::str");
218 let bool_ = resolve_build_in!(ctx, "::core::primitive::bool");
219 let result = resolve_build_in!(ctx, "::core::result::Result");
220 let option = resolve_build_in!(ctx, "::core::option::Option");
221
222 let error = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::Error");
223 let with_serializer = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::WithSerializer");
224 let boxed_serializer =
225 resolve_ident!(ctx, "::xsd_parser_types::quick_xml::BoxedSerializer");
226
227 let code = quote! {
228 impl #with_serializer for #type_ident {
229 type Serializer<'x> = #boxed_serializer<'x>;
230
231 fn serializer<'ser>(
232 &'ser self,
233 name: #option<&'ser #str_>,
234 is_root: #bool_
235 ) -> #result<Self::Serializer<'ser>, #error> {
236 let _name = name;
237
238 self.0.serializer(None, is_root)
239 }
240 }
241 };
242
243 ctx.current_module().append(code);
244 }
245}
246
247impl ReferenceData<'_> {
250 pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
251 let Self {
252 mode,
253 occurs,
254 type_ident,
255 ..
256 } = self;
257
258 if matches!(mode, TypedefMode::Auto | TypedefMode::Typedef) {
259 return;
260 }
261
262 let body = match occurs {
263 Occurs::None => return,
264 Occurs::Single => {
265 quote! {
266 self.0.serialize_bytes(helper)
267 }
268 }
269 Occurs::Optional => {
270 quote! {
271 if let Some(inner) = &self.0 {
272 Ok(Some(inner.serialize_bytes(helper)?))
273 } else {
274 Ok(None)
275 }
276 }
277 }
278 Occurs::DynamicList | Occurs::StaticList(_) => {
279 let string = resolve_build_in!(ctx, "::alloc::string::String");
280
281 let cow = resolve_ident!(ctx, "::alloc::borrow::Cow");
282
283 quote! {
284 if self.0.is_empty() {
285 return Ok(None);
286 }
287
288 let mut data = #string::new();
289 for item in &self.0 {
290 if let Some(bytes) = item.serialize_bytes(helper)? {
291 if !data.is_empty() {
292 data.push(' ');
293 }
294
295 data.push_str(&bytes);
296 }
297 }
298
299 Ok(Some(#cow::Owned(data)))
300 }
301 }
302 };
303
304 let str_ = resolve_build_in!(ctx, "::core::primitive::str");
305 let result = resolve_build_in!(ctx, "::core::result::Result");
306 let option = resolve_build_in!(ctx, "::core::option::Option");
307
308 let cow = resolve_ident!(ctx, "::alloc::borrow::Cow");
309 let error = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::Error");
310 let serialize_bytes = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeBytes");
311 let serialize_helper =
312 resolve_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeHelper");
313 let with_serializer_to_bytes =
314 resolve_ident!(ctx, "xsd_parser_types::quick_xml::WithSerializeToBytes");
315
316 let code = quote! {
317 impl #serialize_bytes for #type_ident {
318 fn serialize_bytes(&self, helper: &mut #serialize_helper) -> #result<#option<#cow<'_, #str_>>, #error> {
319 #body
320 }
321 }
322 impl #with_serializer_to_bytes for #type_ident { }
323 };
324
325 ctx.current_module().append(code);
326 }
327}
328
329impl EnumerationData<'_> {
332 pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
333 let Self {
334 type_ident,
335 variants,
336 ..
337 } = self;
338
339 let variants = variants.iter().map(|x| x.render_serializer_variant(ctx));
340
341 let str_ = resolve_build_in!(ctx, "::core::primitive::str");
342 let result = resolve_build_in!(ctx, "::core::result::Result");
343 let option = resolve_build_in!(ctx, "::core::option::Option");
344
345 let cow = resolve_ident!(ctx, "::alloc::borrow::Cow");
346 let error = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::Error");
347 let serialize_bytes = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeBytes");
348 let serialize_helper =
349 resolve_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeHelper");
350 let with_serializer_to_bytes =
351 resolve_ident!(ctx, "xsd_parser_types::quick_xml::WithSerializeToBytes");
352
353 let code = quote! {
354 impl #serialize_bytes for #type_ident {
355 fn serialize_bytes(&self, helper: &mut #serialize_helper) -> #result<#option<#cow<'_, #str_>>, #error> {
356 match self {
357 #( #variants )*
358 }
359 }
360 }
361 impl #with_serializer_to_bytes for #type_ident { }
362 };
363
364 ctx.current_module().append(code);
365 }
366}
367
368impl EnumerationDataVariant<'_> {
369 fn render_serializer_variant(&self, ctx: &Context<'_, '_>) -> TokenStream {
370 let Self {
371 s_name,
372 target_type,
373 variant_ident,
374 ..
375 } = self;
376
377 if target_type.is_some() {
378 return quote! {
379 Self::#variant_ident(x) => x.serialize_bytes(helper),
380 };
381 }
382
383 match &self.value {
384 EnumerationVariantValue::None => {
385 let cow = resolve_ident!(ctx, "::alloc::borrow::Cow");
386
387 quote! {
388 Self::#variant_ident => Ok(Some(#cow::Borrowed(#s_name))),
389 }
390 }
391 EnumerationVariantValue::ByteLiteral(ident, _) => {
392 let cow = resolve_ident!(ctx, "::alloc::borrow::Cow");
393
394 quote! {
395 Self::#variant_ident => Ok(Some(#cow::Borrowed(Self::#ident))),
396 }
397 }
398 EnumerationVariantValue::Constant(ident, _) => {
399 quote! {
400 Self::#variant_ident => Self::#ident.serialize_bytes(helper),
401 }
402 }
403 }
404 }
405}
406
407impl SimpleData<'_> {
410 pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
411 let Self { type_ident, .. } = self;
412
413 let str_ = resolve_build_in!(ctx, "::core::primitive::str");
414 let result = resolve_build_in!(ctx, "::core::result::Result");
415 let option = resolve_build_in!(ctx, "::core::option::Option");
416
417 let cow = resolve_ident!(ctx, "::alloc::borrow::Cow");
418 let error = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::Error");
419 let serialize_bytes = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeBytes");
420 let serialize_helper =
421 resolve_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeHelper");
422 let with_serializer_to_bytes =
423 resolve_ident!(ctx, "xsd_parser_types::quick_xml::WithSerializeToBytes");
424
425 let body = if let Some(digits) = self.meta.constrains.fraction_digits {
426 let format = format!("{{inner:.0{digits}}}");
427
428 quote! {
429 let Self(inner) = self;
430
431 Ok(Some(#cow::Owned(format!(#format))))
432 }
433 } else if self.meta.is_list {
434 let string = resolve_build_in!(ctx, "::alloc::string::String");
435
436 quote! {
437 if self.0.is_empty() {
438 return Ok(None);
439 }
440
441 let mut data = #string::new();
442 for item in &self.0 {
443 if let Some(bytes) = item.serialize_bytes(helper)? {
444 if !data.is_empty() {
445 data.push(' ');
446 }
447
448 data.push_str(&bytes);
449 }
450 }
451
452 Ok(Some(#cow::Owned(data)))
453 }
454 } else {
455 quote! {
456 self.0.serialize_bytes(helper)
457 }
458 };
459
460 let code = quote! {
461 impl #serialize_bytes for #type_ident {
462 fn serialize_bytes(&self, helper: &mut #serialize_helper) -> #result<#option<#cow<'_, #str_>>, #error> {
463 #body
464 }
465 }
466 impl #with_serializer_to_bytes for #type_ident { }
467 };
468
469 ctx.current_module().append(code);
470 }
471}
472
473impl ComplexData<'_> {
476 pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
477 match self {
478 Self::Enum {
479 type_,
480 content_type,
481 } => {
482 type_.render_serializer(ctx);
483
484 if let Some(content_type) = content_type {
485 content_type.render_serializer(ctx);
486 }
487 }
488 Self::Struct {
489 type_,
490 content_type,
491 } => {
492 type_.render_serializer(ctx);
493
494 if let Some(content_type) = content_type {
495 content_type.render_serializer(ctx);
496 }
497 }
498 }
499 }
500}
501
502impl ComplexBase<'_> {
503 fn render_with_serializer(&self, ctx: &mut Context<'_, '_>, forward_root: bool) {
504 let Self {
505 type_ident,
506 serializer_ident,
507 ..
508 } = self;
509
510 let body = if let Some(tag_name) = &self.element_tag() {
511 let config = ctx.get_ref::<SerializerConfig>();
512 let tag_name = tag_name.get_for_default_namespace(&config.default_namespace);
513
514 self.render_with_serializer_for_element(ctx, &tag_name)
515 } else {
516 self.render_with_serializer_for_content(ctx, forward_root)
517 };
518
519 let str_ = resolve_build_in!(ctx, "::core::primitive::str");
520 let bool_ = resolve_build_in!(ctx, "::core::primitive::bool");
521 let result = resolve_build_in!(ctx, "::core::result::Result");
522 let option = resolve_build_in!(ctx, "::core::option::Option");
523
524 let error = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::Error");
525 let with_serializer = resolve_ident!(ctx, "::xsd_parser_types::quick_xml::WithSerializer");
526
527 let code = quote! {
528 impl #with_serializer for #type_ident {
529 type Serializer<'x> = quick_xml_serialize::#serializer_ident<'x>;
530
531 fn serializer<'ser>(
532 &'ser self,
533 name: #option<&'ser #str_>,
534 is_root: #bool_,
535 ) -> #result<Self::Serializer<'ser>, #error> {
536 #body
537 }
538 }
539 };
540
541 ctx.current_module().append(code);
542 }
543
544 fn render_with_serializer_for_element(
545 &self,
546 ctx: &Context<'_, '_>,
547 tag_name: &str,
548 ) -> TokenStream {
549 let Self {
550 serializer_ident,
551 serializer_state_ident,
552 ..
553 } = self;
554
555 let box_ = resolve_build_in!(ctx, "::alloc::boxed::Box");
556
557 quote! {
558 Ok(quick_xml_serialize::#serializer_ident {
559 value: self,
560 state: #box_::new(quick_xml_serialize::#serializer_state_ident::Init__),
561 name: name.unwrap_or(#tag_name),
562 is_root,
563 })
564 }
565 }
566
567 fn render_with_serializer_for_content(
568 &self,
569 ctx: &Context<'_, '_>,
570 forward_root: bool,
571 ) -> TokenStream {
572 let Self {
573 serializer_ident,
574 serializer_state_ident,
575 ..
576 } = self;
577
578 let drop_root = (!forward_root).then(|| quote!(let _is_root = is_root;));
579 let forward_root = forward_root.then(|| quote!(is_root,));
580
581 let box_ = resolve_build_in!(ctx, "::alloc::boxed::Box");
582
583 quote! {
584 let _name = name;
585 #drop_root
586
587 Ok(quick_xml_serialize::#serializer_ident {
588 value: self,
589 state: #box_::new(quick_xml_serialize::#serializer_state_ident::Init__),
590 #forward_root
591 })
592 }
593 }
594
595 fn render_serializer_type(&self, ctx: &mut Context<'_, '_>, forward_root: bool) {
596 let Self {
597 type_ident,
598 serializer_ident,
599 serializer_state_ident,
600 ..
601 } = self;
602
603 let box_ = resolve_build_in!(ctx, "::alloc::boxed::Box");
604 let str_ = resolve_build_in!(ctx, "::core::primitive::str");
605 let bool_ = resolve_build_in!(ctx, "::core::primitive::bool");
606
607 let name = self.represents_element().then(|| {
608 quote! {
609 pub(super) name: &'ser #str_,
610 }
611 });
612 let is_root = forward_root.then(|| {
613 quote! {
614 pub(super) is_root: #bool_,
615 }
616 });
617
618 let code = quote! {
619 #[derive(Debug)]
620 pub struct #serializer_ident<'ser> {
621 pub(super) value: &'ser super::#type_ident,
622 pub(super) state: #box_<#serializer_state_ident<'ser>>,
623 #name
624 #is_root
625 }
626 };
627
628 ctx.quick_xml_serialize().append(code);
629 }
630
631 fn render_serializer_handle_state_end(
632 &self,
633 ctx: &Context<'_, '_>,
634 need_ns_scope: bool,
635 ) -> TokenStream {
636 let serializer_state_ident = &self.serializer_state_ident;
637
638 let event = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Event");
639 let bytes_end = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::BytesEnd");
640
641 let end_ns_scope = need_ns_scope.then(|| quote!(helper.end_ns_scope();));
642
643 quote! {
644 #serializer_state_ident::End__ => {
645 *self.state = #serializer_state_ident::Done__;
646
647 #end_ns_scope
648
649 return Ok(Some(
650 #event::End(
651 #bytes_end::new(self.name))
652 )
653 );
654 }
655 }
656 }
657
658 #[allow(clippy::too_many_lines)]
659 fn render_serializer_bytes_ctor(
660 &self,
661 ctx: &mut Context<'_, '_>,
662 attributes: &[ComplexDataAttribute<'_>],
663 ) -> (TokenStream, bool) {
664 let attributes_ctor = attributes.iter().map(|attrib| {
665 let attrib_name = attrib.tag_name.get(true);
666 let field_ident = &attrib.ident;
667
668 if attrib.meta.is_any() {
669 quote! {
670 bytes.extend_attributes(self.value.#field_ident.attributes());
671 }
672 } else if attrib.is_option {
673 quote! {
674 helper.write_attrib_opt(&mut bytes, #attrib_name, &self.value.#field_ident)?;
675 }
676 } else {
677 quote! {
678 helper.write_attrib(&mut bytes, #attrib_name, &self.value.#field_ident)?;
679 }
680 }
681 });
682
683 let config = ctx.get_ref::<SerializerConfig>();
684 let namespaces = config.namespaces;
685 let default_namespace = config.default_namespace.clone();
686 let xmlns = match namespaces {
687 NamespaceSerialization::None => None,
688 NamespaceSerialization::Local => {
689 let mut xmlns = Vec::new();
690 let mut cache = HashSet::new();
691
692 let element_module = self
693 .tag_name
694 .as_ref()
695 .and_then(|tag| {
696 let module = tag.module?;
697 let form = if matches!((&default_namespace, &module.namespace), (Some(a), Some(b)) if a == b) {
698 FormChoiceType::Unqualified
699 } else {
700 tag.form
701 };
702
703 Some((form, module))
704 })
705 .into_iter();
706 let attribute_modules = attributes
707 .iter()
708 .filter_map(|attrib| {
709 (attrib.tag_name.form == FormChoiceType::Qualified)
710 .then_some(attrib.tag_name.module?)
711 })
712 .map(|module| (FormChoiceType::Qualified, module));
713
714 for (form, module) in element_module.chain(attribute_modules) {
715 if !cache.insert(module.namespace_id) {
716 continue;
717 }
718
719 let Some(path) = module.make_ns_const() else {
720 continue;
721 };
722
723 let ns_const = ctx.resolve_type_for_serialize_module(&path);
724 let prefix_const = (form == FormChoiceType::Qualified)
725 .then(|| module.make_prefix_const())
726 .flatten()
727 .map(|path| ctx.resolve_type_for_serialize_module(&path))
728 .map_or_else(|| quote!(None), |x| quote!(Some(&#x)));
729
730 xmlns.push(quote! {
731 helper.write_xmlns(&mut bytes, #prefix_const, &#ns_const);
732 });
733 }
734
735 xmlns.is_empty().not().then(|| {
736 quote! {
737 #( #xmlns )*
738 }
739 })
740 }
741 NamespaceSerialization::Global => {
742 let nillable_type_support =
743 ctx.check_generator_flags(GeneratorFlags::NILLABLE_TYPE_SUPPORT);
744 let types: &MetaTypes = ctx.types;
745 let collector = ctx
746 .get_or_create_with::<NamespaceCollector, _>(|| {
747 NamespaceCollector::new(types, nillable_type_support)
748 })
749 .clone();
750 let mut collector = collector.borrow_mut();
751
752 let xmlns = self.tag_name.as_ref().and_then(|x| x.render_xmlns(ctx));
753
754 let global_xmlns = collector
755 .get_namespaces(ctx.types, ctx.ident, default_namespace.as_ref())
756 .values()
757 .map(|(prefix, namespace)| {
758 let ns_const = ctx.resolve_type_for_serialize_module(namespace);
759 let prefix_const = prefix.as_ref().map_or_else(
760 || quote!(None),
761 |prefix| {
762 let x = ctx.resolve_type_for_serialize_module(prefix);
763
764 quote!(Some(&#x))
765 },
766 );
767
768 quote! {
769 helper.write_xmlns(&mut bytes, #prefix_const, &#ns_const);
770 }
771 })
772 .collect::<Vec<_>>();
773 let global_xmlns = global_xmlns.is_empty().not().then(|| {
774 quote! {
775 if self.is_root {
776 #( #global_xmlns )*
777 }
778 }
779 });
780
781 (xmlns.is_some() || global_xmlns.is_some()).then(|| {
782 quote! {
783 #xmlns
784 #global_xmlns
785 }
786 })
787 }
788 NamespaceSerialization::Dynamic => {
789 let xmlns = self.tag_name.as_ref().and_then(|x| x.render_xmlns(ctx));
790
791 let collect_namespaces = resolve_quick_xml_ident!(
792 ctx,
793 "::xsd_parser_types::quick_xml::CollectNamespaces"
794 );
795
796 Some(quote! {
797 #xmlns
798 if self.is_root {
799 #collect_namespaces::collect_namespaces(self.value, helper, &mut bytes);
800 }
801 })
802 }
803 };
804
805 let mut_ = xmlns.is_some() || !attributes.is_empty();
806 let mut_ = mut_.then(|| quote!(mut));
807
808 let bytes_start =
809 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::BytesStart");
810
811 let need_ns_scope = xmlns.is_some();
812 let begin_ns_scope = need_ns_scope.then(|| quote!(helper.begin_ns_scope();));
813 let code = quote! {
814 let #mut_ bytes = #bytes_start::new(self.name);
815 #begin_ns_scope
816 #xmlns
817 #( #attributes_ctor )*
818 };
819
820 (code, need_ns_scope)
821 }
822}
823
824impl ComplexDataEnum<'_> {
825 fn serializer_need_end_state(&self) -> bool {
826 self.represents_element()
827 }
828
829 fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
830 self.render_with_serializer(ctx, !self.is_content());
831 self.render_serializer_type(ctx, !self.is_content());
832 self.render_serializer_state_type(ctx);
833 self.render_serializer_impl(ctx);
834 }
835
836 fn render_serializer_state_type(&self, ctx: &mut Context<'_, '_>) {
837 let serializer_state_ident = &self.serializer_state_ident;
838
839 let state_variants = self
840 .elements
841 .iter()
842 .map(|x| x.render_serializer_state_variant(ctx));
843 let state_end = self.represents_element().then(|| {
844 quote! {
845 End__,
846 }
847 });
848
849 let code = quote! {
850 #[derive(Debug)]
851 pub(super) enum #serializer_state_ident<'ser> {
852 Init__,
853 #( #state_variants )*
854 #state_end
855 Done__,
856 Phantom__(&'ser ()),
857 }
858 };
859
860 ctx.quick_xml_serialize().append(code);
861 }
862
863 fn render_serializer_impl(&self, ctx: &mut Context<'_, '_>) {
864 let serializer_ident = &self.serializer_ident;
865 let serializer_state_ident = &self.serializer_state_ident;
866
867 let (emit_start_event, handle_state_end) = self
868 .serializer_need_end_state()
869 .then(|| {
870 let (emit_start_event, need_ns_scope) =
871 self.render_serializer_impl_start_event(ctx);
872 let handle_state_end = self.render_serializer_handle_state_end(ctx, need_ns_scope);
873
874 (emit_start_event, handle_state_end)
875 })
876 .unzip();
877
878 let final_state = if self.serializer_need_end_state() {
879 quote!(#serializer_state_ident::End__)
880 } else {
881 quote!(#serializer_state_ident::Done__)
882 };
883
884 let variants_init = self.elements.iter().map(|element| {
885 let type_ident = &self.type_ident;
886 let variant_ident = &element.variant_ident;
887 let init = element.render_serializer_enum_state_init(
888 ctx,
889 &self.serializer_state_ident,
890 !self.is_content(),
891 );
892
893 quote! {
894 super::#type_ident::#variant_ident(x) => #init,
895 }
896 });
897
898 let handle_state_init = quote! {
899 match self.value {
900 #( #variants_init )*
901 }
902 };
903
904 let handle_state_variants = self.elements.iter().map(|element| {
905 let variant_ident = &element.variant_ident;
906
907 quote! {
908 #serializer_state_ident::#variant_ident(x) => {
909 match x.next(helper).transpose()? {
910 Some(event) => return Ok(Some(event)),
911 None => *self.state = #final_state,
912 }
913 }
914 }
915 });
916
917 let result = resolve_build_in!(ctx, "::core::result::Result");
918 let option = resolve_build_in!(ctx, "::core::option::Option");
919
920 let event = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Event");
921 let error = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Error");
922 let serializer = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Serializer");
923 let serialize_helper =
924 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeHelper");
925
926 ctx.add_quick_xml_serialize_usings(true, ["::xsd_parser_types::quick_xml::Serializer"]);
927
928 let code = quote! {
929 impl<'ser> #serializer_ident<'ser> {
930 fn next_event(&mut self, helper: &mut #serialize_helper) -> #result<#option<#event<'ser>>, #error> {
931 loop {
932 match &mut *self.state {
933 #serializer_state_ident::Init__ => {
934 #handle_state_init
935 #emit_start_event
936 }
937 #( #handle_state_variants )*
938 #handle_state_end
939 #serializer_state_ident::Done__ => return Ok(None),
940 #serializer_state_ident::Phantom__(_) => unreachable!(),
941 }
942 }
943 }
944 }
945
946 impl<'ser> #serializer<'ser> for #serializer_ident<'ser> {
947 fn next(&mut self, helper: &mut #serialize_helper) -> #option<#result<#event<'ser>, #error>> {
948 match self.next_event(helper) {
949 Ok(Some(event)) => Some(Ok(event)),
950 Ok(None) => None,
951 Err(error) => {
952 *self.state = #serializer_state_ident::Done__;
953
954 Some(Err(error))
955 }
956 }
957 }
958 }
959 };
960
961 ctx.quick_xml_serialize().append(code);
962 }
963
964 fn render_serializer_impl_start_event(&self, ctx: &mut Context<'_, '_>) -> (TokenStream, bool) {
965 let event = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Event");
966
967 let (bytes_ctor, need_ns_scope) = self.render_serializer_bytes_ctor(ctx, &[]);
968
969 let code = quote! {
970 #bytes_ctor
971 return Ok(Some(#event::Start(bytes)))
972 };
973
974 (code, need_ns_scope)
975 }
976}
977
978impl ComplexDataStruct<'_> {
979 fn serializer_need_end_state(&self) -> bool {
980 self.represents_element() && self.has_content()
981 }
982
983 fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
984 self.render_with_serializer(ctx, self.represents_element());
985 self.render_serializer_type(ctx, self.represents_element());
986 self.render_serializer_state_type(ctx);
987 self.render_serializer_impl(ctx);
988 }
989
990 fn render_serializer_state_type(&self, ctx: &mut Context<'_, '_>) {
991 let state_ident = &self.serializer_state_ident;
992
993 let state_variants = self
994 .elements()
995 .iter()
996 .map(|x| x.render_serializer_state_variant(ctx));
997 let state_content = self
998 .content()
999 .and_then(|x| x.render_serializer_state_variant(ctx));
1000 let state_end = self.serializer_need_end_state().then(|| {
1001 quote! {
1002 End__,
1003 }
1004 });
1005
1006 let code = quote! {
1007 #[derive(Debug)]
1008 pub(super) enum #state_ident<'ser> {
1009 Init__,
1010 #( #state_variants )*
1011 #state_content
1012 #state_end
1013 Done__,
1014 Phantom__(&'ser ()),
1015 }
1016 };
1017
1018 ctx.quick_xml_serialize().append(code);
1019 }
1020
1021 #[allow(clippy::too_many_lines)]
1022 fn render_serializer_impl(&self, ctx: &mut Context<'_, '_>) {
1023 let serializer_ident = &self.serializer_ident;
1024 let serializer_state_ident = &self.serializer_state_ident;
1025
1026 let (emit_start_event, handle_state_end) = self
1027 .represents_element()
1028 .then(|| {
1029 let (emit_start_event, need_ns_scope) =
1030 self.render_serializer_impl_start_event(ctx);
1031 let handle_state_end = self
1032 .serializer_need_end_state()
1033 .then(|| self.render_serializer_handle_state_end(ctx, need_ns_scope));
1034
1035 (emit_start_event, handle_state_end)
1036 })
1037 .unzip();
1038 let handle_state_end = handle_state_end.flatten();
1039
1040 let final_state = if self.serializer_need_end_state() {
1041 quote!(#serializer_state_ident::End__)
1042 } else {
1043 quote!(#serializer_state_ident::Done__)
1044 };
1045
1046 let elements = self.elements();
1047 let handle_state_init = if let Some(first) = elements.first() {
1048 let init = first.render_serializer_struct_state_init(ctx, serializer_state_ident);
1049
1050 quote!(#init;)
1051 } else if let Some(content) = &self.content() {
1052 let init = content.render_serializer_state_init(ctx, serializer_state_ident);
1053
1054 quote!(#init;)
1055 } else {
1056 quote!(*self.state = #final_state;)
1057 };
1058
1059 let handle_state_variants = (0..).take(elements.len()).map(|i| {
1060 let element = &elements[i];
1061 let variant_ident = &element.variant_ident;
1062
1063 let next = if let Some(next) = elements.get(i + 1) {
1064 let init = next.render_serializer_struct_state_init(ctx, serializer_state_ident);
1065
1066 quote!(#init,)
1067 } else {
1068 quote! {
1069 *self.state = #final_state,
1070 }
1071 };
1072
1073 quote! {
1074 #serializer_state_ident::#variant_ident(x) => match x.next(helper).transpose()? {
1075 Some(event) => return Ok(Some(event)),
1076 None => #next
1077 }
1078 }
1079 });
1080
1081 let handle_state_content = self.content().map(|_| {
1082 quote! {
1083 #serializer_state_ident::Content__(x) => match x.next(helper).transpose()? {
1084 Some(event) => return Ok(Some(event)),
1085 None => *self.state = #final_state,
1086 }
1087 }
1088 });
1089
1090 let result = resolve_build_in!(ctx, "::core::result::Result");
1091 let option = resolve_build_in!(ctx, "::core::option::Option");
1092
1093 let event = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Event");
1094 let error = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Error");
1095 let serializer = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Serializer");
1096 let serialize_helper =
1097 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::SerializeHelper");
1098
1099 ctx.add_quick_xml_serialize_usings(true, ["::xsd_parser_types::quick_xml::Serializer"]);
1100
1101 let code = quote! {
1102 impl<'ser> #serializer_ident<'ser> {
1103 fn next_event(&mut self, helper: &mut #serialize_helper) -> #result<#option<#event<'ser>>, #error> {
1104 loop {
1105 match &mut *self.state {
1106 #serializer_state_ident::Init__ => {
1107 #handle_state_init
1108 #emit_start_event
1109 }
1110 #( #handle_state_variants )*
1111 #handle_state_content
1112 #handle_state_end
1113 #serializer_state_ident::Done__ => return Ok(None),
1114 #serializer_state_ident::Phantom__(_) => unreachable!(),
1115 }
1116 }
1117 }
1118 }
1119
1120 impl<'ser> #serializer<'ser> for #serializer_ident<'ser> {
1121 fn next(&mut self, helper: &mut #serialize_helper) -> #option<#result<#event<'ser>, #error>> {
1122 match self.next_event(helper) {
1123 Ok(Some(event)) => Some(Ok(event)),
1124 Ok(None) => None,
1125 Err(error) => {
1126 *self.state = #serializer_state_ident::Done__;
1127
1128 Some(Err(error))
1129 }
1130 }
1131 }
1132 }
1133 };
1134
1135 ctx.quick_xml_serialize().append(code);
1136 }
1137
1138 fn render_serializer_impl_start_event(&self, ctx: &mut Context<'_, '_>) -> (TokenStream, bool) {
1139 let event = resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::Event");
1140
1141 let (bytes_ctor, need_ns_scope) = self.render_serializer_bytes_ctor(ctx, &self.attributes);
1142 let end_ns_scope =
1143 (need_ns_scope && !self.has_content()).then(|| quote!(helper.end_ns_scope();));
1144
1145 let variant = if self.has_content() {
1146 format_ident!("Start")
1147 } else {
1148 format_ident!("Empty")
1149 };
1150
1151 let code = quote! {
1152 #bytes_ctor
1153 #end_ns_scope
1154
1155 return Ok(Some(#event::#variant(bytes)))
1156 };
1157
1158 (code, need_ns_scope)
1159 }
1160}
1161
1162impl ComplexDataContent<'_> {
1163 fn render_serializer_state_variant(&self, ctx: &Context<'_, '_>) -> Option<TokenStream> {
1164 let serializer = self.occurs.make_serializer_type(
1165 ctx,
1166 &ctx.resolve_type_for_serialize_module(&self.target_type),
1167 false,
1168 )?;
1169
1170 Some(quote! {
1171 Content__(#serializer),
1172 })
1173 }
1174
1175 fn render_serializer_state_init(
1176 &self,
1177 ctx: &Context<'_, '_>,
1178 state_ident: &Ident2,
1179 ) -> TokenStream {
1180 match self.occurs {
1181 Occurs::None => crate::unreachable!(),
1182 Occurs::Single => {
1183 let with_serializer =
1184 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::WithSerializer");
1185
1186 quote! {
1187 *self.state = #state_ident::Content__(
1188 #with_serializer::serializer(&self.value.content, None, false)?
1189 )
1190 }
1191 }
1192 Occurs::Optional => {
1193 let iter_serializer =
1194 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::IterSerializer");
1195
1196 quote! {
1197 *self.state = #state_ident::Content__(
1198 #iter_serializer::new(
1199 self.value.content.as_ref(),
1200 None,
1201 false
1202 )
1203 )
1204 }
1205 }
1206 Occurs::DynamicList | Occurs::StaticList(_) => {
1207 let iter_serializer =
1208 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::IterSerializer");
1209
1210 quote! {
1211 *self.state = #state_ident::Content__(
1212 #iter_serializer::new(
1213 &self.value.content[..],
1214 None,
1215 false
1216 )
1217 )
1218 }
1219 }
1220 }
1221 }
1222}
1223
1224impl ComplexDataElement<'_> {
1225 fn render_serializer_state_variant(&self, ctx: &Context<'_, '_>) -> TokenStream {
1226 let target_type = ctx.resolve_type_for_serialize_module(&self.target_type);
1227 let variant_ident = &self.variant_ident;
1228 let serializer = self
1229 .occurs
1230 .make_serializer_type(ctx, &target_type, self.need_indirection);
1231
1232 quote! {
1233 #variant_ident(#serializer),
1234 }
1235 }
1236
1237 fn render_serializer_enum_state_init(
1238 &self,
1239 ctx: &Context<'_, '_>,
1240 state_ident: &Ident2,
1241 forward_root: bool,
1242 ) -> TokenStream {
1243 let value = match self.occurs {
1244 Occurs::None => unreachable!(),
1245 Occurs::Single if self.need_indirection => quote!(&**x),
1246 Occurs::Single => quote!(x),
1247 Occurs::Optional if self.need_indirection => quote!(x.as_deref()),
1248 Occurs::Optional => quote!(x.as_ref()),
1249 Occurs::DynamicList | Occurs::StaticList(_) => quote!(&x[..]),
1250 };
1251
1252 self.render_serializer_state_init(ctx, state_ident, &value, forward_root)
1253 }
1254
1255 fn render_serializer_struct_state_init(
1256 &self,
1257 ctx: &Context<'_, '_>,
1258 state_ident: &Ident2,
1259 ) -> TokenStream {
1260 let field_ident = &self.field_ident;
1261
1262 let value = match self.occurs {
1263 Occurs::None => unreachable!(),
1264 Occurs::Single if self.need_indirection => quote!(&*self.value.#field_ident),
1265 Occurs::Single => quote!(&self.value.#field_ident),
1266 Occurs::Optional if self.need_indirection => {
1267 quote!(self.value.#field_ident.as_deref())
1268 }
1269 Occurs::Optional => quote!(self.value.#field_ident.as_ref()),
1270 Occurs::DynamicList | Occurs::StaticList(_) => quote!(&self.value.#field_ident[..]),
1271 };
1272
1273 self.render_serializer_state_init(ctx, state_ident, &value, false)
1274 }
1275
1276 fn render_serializer_state_init(
1277 &self,
1278 ctx: &Context<'_, '_>,
1279 state_ident: &Ident2,
1280 value: &TokenStream,
1281 forward_root: bool,
1282 ) -> TokenStream {
1283 let config = ctx.get_ref::<SerializerConfig>();
1284 let field_name = self
1285 .tag_name
1286 .get_for_default_namespace(&config.default_namespace);
1287 let variant_ident = &self.variant_ident;
1288
1289 let is_root = if forward_root {
1290 quote!(self.is_root)
1291 } else {
1292 quote!(false)
1293 };
1294
1295 let element_name = self
1296 .meta()
1297 .is_any()
1298 .then(|| quote!(None))
1299 .unwrap_or_else(|| quote!(Some(#field_name)));
1300
1301 match self.occurs {
1302 Occurs::None => crate::unreachable!(),
1303 Occurs::Single => {
1304 let with_serializer =
1305 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::WithSerializer");
1306
1307 quote! {
1308 *self.state = #state_ident::#variant_ident(
1309 #with_serializer::serializer(#value, #element_name, #is_root)?
1310 )
1311 }
1312 }
1313 Occurs::StaticList(_) if self.need_indirection => {
1314 let deref_iter =
1315 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::DerefIter");
1316 let iter_serializer =
1317 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::IterSerializer");
1318
1319 quote! {
1320 *self.state = #state_ident::#variant_ident(
1321 #iter_serializer::new(
1322 #deref_iter::new(#value),
1323 #element_name,
1324 #is_root
1325 )
1326 )
1327 }
1328 }
1329 Occurs::Optional | Occurs::DynamicList | Occurs::StaticList(_) => {
1330 let iter_serializer =
1331 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::IterSerializer");
1332
1333 quote! {
1334 *self.state = #state_ident::#variant_ident(
1335 #iter_serializer::new(
1336 #value,
1337 #element_name,
1338 #is_root
1339 )
1340 )
1341 }
1342 }
1343 }
1344 }
1345}
1346
1347impl Occurs {
1348 fn make_serializer_type(
1349 &self,
1350 ctx: &Context<'_, '_>,
1351 target_type: &TokenStream,
1352 need_indirection: bool,
1353 ) -> Option<TokenStream> {
1354 match self {
1355 Occurs::None => None,
1356 Occurs::Single => {
1357 let with_serializer =
1358 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::WithSerializer");
1359
1360 Some(quote!(<#target_type as #with_serializer>::Serializer<'ser>))
1361 }
1362 Occurs::Optional => {
1363 let option = resolve_build_in!(ctx, "::core::option::Option");
1364
1365 let iter_serializer =
1366 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::IterSerializer");
1367
1368 Some(quote!(#iter_serializer<'ser, #option<&'ser #target_type>, #target_type>))
1369 }
1370 Occurs::StaticList(..) if need_indirection => {
1371 let box_ = resolve_build_in!(ctx, "::alloc::boxed::Box");
1372
1373 let deref_iter =
1374 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::DerefIter");
1375 let iter_serializer =
1376 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::IterSerializer");
1377
1378 Some(
1379 quote!(#iter_serializer<'ser, #deref_iter<&'ser [#box_<#target_type>]>, #target_type>),
1380 )
1381 }
1382 Occurs::DynamicList | Occurs::StaticList(..) => {
1383 let iter_serializer =
1384 resolve_quick_xml_ident!(ctx, "::xsd_parser_types::quick_xml::IterSerializer");
1385
1386 Some(quote!(#iter_serializer<'ser, &'ser [#target_type], #target_type>))
1387 }
1388 }
1389 }
1390}
1391
1392impl TagName<'_> {
1393 fn render_xmlns(&self, ctx: &mut Context<'_, '_>) -> Option<TokenStream> {
1394 let module = self.module?;
1395 if self.form != FormChoiceType::Qualified || module.prefix().is_some() {
1396 return None;
1397 }
1398
1399 let ns = module.make_ns_const()?;
1400 let ns_const = ctx.resolve_type_for_serialize_module(&ns);
1401
1402 Some(quote!(helper.write_xmlns(&mut bytes, None, &#ns_const);))
1403 }
1404}
1405
1406impl ValueKey for NamespaceCollector {
1407 type Type = Rc<RefCell<Self>>;
1408}
1409
1410#[derive(Debug)]
1411enum GetNamespaceState {
1412 Empty,
1413 Weak(GlobalNamespaces),
1414 Strong(GlobalNamespaces),
1415 Shared(SharedGlobalNamespaces),
1416}
1417
1418impl NamespaceCollector {
1419 fn new(types: &MetaTypes, nillable_type_support: bool) -> Rc<RefCell<Self>> {
1420 let xsi_namespace = types.modules.iter().find_map(|(id, module)| {
1421 if matches!(module.namespace.as_ref(), Some(ns) if *ns == Namespace::XSI) {
1422 Some(*id)
1423 } else {
1424 None
1425 }
1426 });
1427
1428 Rc::new(RefCell::new(Self {
1429 cache: HashMap::new(),
1430 xsi_namespace,
1431 nillable_type_support,
1432 }))
1433 }
1434
1435 fn get_namespaces(
1436 &mut self,
1437 types: &MetaTypes,
1438 ident: &TypeIdent,
1439 default_ns: Option<&Namespace>,
1440 ) -> &SharedGlobalNamespaces {
1441 self.get_namespaces_impl(types, ident, default_ns).unwrap()
1442 }
1443
1444 #[allow(clippy::too_many_lines)]
1445 fn get_namespaces_impl(
1446 &mut self,
1447 types: &MetaTypes,
1448 ident: &TypeIdent,
1449 default_ns: Option<&Namespace>,
1450 ) -> Option<&SharedGlobalNamespaces> {
1451 let create = match self.cache.entry(ident.clone()) {
1452 HashMapEntry::Vacant(e) => {
1453 e.insert(None);
1454
1455 true
1456 }
1457 HashMapEntry::Occupied(_) => false,
1458 };
1459
1460 let new_value = if create {
1461 let ty = types.items.get(ident).unwrap();
1462 let mut state = GetNamespaceState::Empty;
1463
1464 match &ty.variant {
1465 MetaTypeVariant::Union(x) => {
1466 for ty in &*x.types {
1467 self.merge(&mut state, types, &ty.type_, default_ns);
1468 }
1469 }
1470 MetaTypeVariant::Reference(x) => {
1471 self.merge(&mut state, types, &x.type_, default_ns);
1472 if self.nillable_type_support && x.nillable {
1473 if let Some(id) = self.xsi_namespace {
1474 Self::add_ns(&mut state, types, NamespaceKey::Normal(id));
1475 }
1476 }
1477 }
1478 MetaTypeVariant::Enumeration(x) => {
1479 for var in &*x.variants {
1480 if let Some(ident) = &var.type_ {
1481 self.merge(&mut state, types, ident, default_ns);
1482 }
1483 }
1484 }
1485 MetaTypeVariant::Dynamic(x) => {
1486 for meta in &x.derived_types {
1487 self.merge(&mut state, types, &meta.type_, default_ns);
1488 }
1489 }
1490 MetaTypeVariant::All(x)
1491 | MetaTypeVariant::Choice(x)
1492 | MetaTypeVariant::Sequence(x) => {
1493 for el in &*x.elements {
1494 if let ElementMetaVariant::Type { type_, .. } = &el.variant {
1495 self.merge(&mut state, types, type_, default_ns);
1496 }
1497 if self.nillable_type_support && el.nillable {
1498 if let Some(id) = self.xsi_namespace {
1499 Self::add_ns(&mut state, types, NamespaceKey::Normal(id));
1500 }
1501 }
1502 }
1503 }
1504 MetaTypeVariant::ComplexType(x) => {
1505 if let Some(ident) = &x.content {
1506 self.merge(&mut state, types, ident, default_ns);
1507 }
1508
1509 for attrib in &*x.attributes {
1510 if attrib.form == FormChoiceType::Qualified {
1511 Self::add_ns(&mut state, types, NamespaceKey::Normal(attrib.ident.ns));
1512 }
1513 }
1514 }
1515 MetaTypeVariant::Custom(x) => {
1516 for ns in x.namespaces() {
1517 let key = match ns {
1518 CustomMetaNamespace::Id(id) => NamespaceKey::Default(*id),
1519 CustomMetaNamespace::Namespace(ns) => {
1520 let id = types.modules.iter().find_map(|(id, module)| {
1521 matches!(module.namespace.as_ref(), Some(x) if x == ns)
1522 .then_some(*id)
1523 });
1524 let Some(id) = id else {
1525 continue;
1526 };
1527
1528 NamespaceKey::Normal(id)
1529 }
1530 };
1531
1532 Self::add_ns(&mut state, types, key);
1533 }
1534 }
1535 MetaTypeVariant::BuildIn(_) | MetaTypeVariant::SimpleType(_) => (),
1536 }
1537
1538 if ty.form() == FormChoiceType::Qualified {
1539 let ns = types
1540 .modules
1541 .get(&ident.ns)
1542 .and_then(|module| module.namespace.as_ref());
1543
1544 let key = if matches!((ns, default_ns), (Some(a), Some(b)) if a == b) {
1545 NamespaceKey::Default(ident.ns)
1546 } else {
1547 NamespaceKey::Normal(ident.ns)
1548 };
1549
1550 Self::add_ns(&mut state, types, key);
1551 }
1552
1553 let value = match state {
1554 GetNamespaceState::Empty => Default::default(),
1555 GetNamespaceState::Shared(value) => value,
1556 GetNamespaceState::Weak(value) | GetNamespaceState::Strong(value) => Rc::new(value),
1557 };
1558
1559 Some(value)
1560 } else {
1561 None
1562 };
1563
1564 match self.cache.entry(ident.clone()) {
1565 HashMapEntry::Occupied(mut e) => {
1566 if let Some(value) = new_value {
1567 e.insert(Some(value));
1568 }
1569
1570 e.into_mut().as_ref()
1571 }
1572 HashMapEntry::Vacant(_) => unreachable!(),
1573 }
1574 }
1575
1576 fn merge(
1577 &mut self,
1578 state: &mut GetNamespaceState,
1579 types: &MetaTypes,
1580 ident: &TypeIdent,
1581 default_ns: Option<&Namespace>,
1582 ) {
1583 let Some(src) = self.get_namespaces_impl(types, ident, default_ns) else {
1584 return;
1585 };
1586
1587 match replace(state, GetNamespaceState::Empty) {
1588 GetNamespaceState::Empty => *state = GetNamespaceState::Shared(src.clone()),
1589 GetNamespaceState::Weak(dst) => {
1590 *state = GetNamespaceState::Shared(src.clone());
1591
1592 for ns in dst.into_keys() {
1593 Self::add_ns(state, types, ns);
1594 }
1595 }
1596 GetNamespaceState::Shared(dst) if Rc::ptr_eq(&dst, src) => {
1597 *state = GetNamespaceState::Shared(dst);
1598 }
1599 s => {
1600 *state = s;
1601
1602 for ns in src.keys() {
1603 Self::add_ns(state, types, *ns);
1604 }
1605 }
1606 }
1607 }
1608
1609 fn add_ns(state: &mut GetNamespaceState, types: &MetaTypes, key: NamespaceKey) {
1610 match state {
1611 GetNamespaceState::Empty => {
1612 if let Some(value) = Self::make_value(types, key) {
1613 let mut map = GlobalNamespaces::new();
1614 map.insert(key, value);
1615
1616 *state = GetNamespaceState::Weak(map);
1617 }
1618 }
1619 GetNamespaceState::Weak(map) | GetNamespaceState::Strong(map) => {
1620 if let Entry::Vacant(e) = map.entry(key) {
1621 if let Some(value) = Self::make_value(types, key) {
1622 e.insert(value);
1623 }
1624 }
1625 }
1626 GetNamespaceState::Shared(map) => {
1627 if !map.contains_key(&key) {
1628 if let Some(value) = Self::make_value(types, key) {
1629 let mut map = (**map).clone();
1630 map.insert(key, value);
1631
1632 *state = GetNamespaceState::Strong(map);
1633 }
1634 }
1635 }
1636 }
1637 }
1638
1639 fn make_value(types: &MetaTypes, key: NamespaceKey) -> Option<(Option<PathData>, PathData)> {
1640 match key {
1641 NamespaceKey::Normal(id) => {
1642 let module = types.modules.get(&id)?;
1643
1644 let prefix = Some(module.make_prefix_const()?);
1645 let namespace = module.make_ns_const()?;
1646
1647 Some((prefix, namespace))
1648 }
1649 NamespaceKey::Default(id) => {
1650 let module = types.modules.get(&id)?;
1651 let namespace = module.make_ns_const()?;
1652
1653 Some((None, namespace))
1654 }
1655 }
1656 }
1657}