Skip to main content

xsd_parser/pipeline/renderer/steps/quick_xml/
serialize.rs

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