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::{
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/// Implements a [`RenderStep`] that renders the code for the `quick_xml` serialization.
34#[derive(Debug, Clone)]
35pub struct QuickXmlSerializeRenderStep {
36    /// How to serialize namespace definitions.
37    pub namespaces: NamespaceSerialization,
38
39    /// Default namespace to use for the serialization.
40    pub default_namespace: Option<Namespace>,
41}
42
43/// Defines how the [`QuickXmlSerializeRenderStep`] will serialize the different
44/// namespaces of the elements and attributes.
45#[derive(Debug, Clone, Copy, Eq, PartialEq)]
46pub enum NamespaceSerialization {
47    /// Do not serialize any namespace definitions.
48    None,
49
50    /// All namespace definitions are added to the local element if they are
51    /// not already in scope.
52    Local,
53
54    /// All namespace definitions are serialized to the root element.
55    Global,
56
57    /// Namespace definitions are collected at runtime by traversing the value
58    /// tree via the [`CollectNamespaces`](xsd_parser_types::quick_xml::CollectNamespaces)
59    /// trait, and only the namespaces that are actually needed by the current
60    /// value are written to the root element.
61    ///
62    /// This requires the [`QuickXmlCollectNamespacesRenderStep`](super::QuickXmlCollectNamespacesRenderStep)
63    /// to be added to the renderer pipeline as well, so that `CollectNamespaces`
64    /// is implemented for all generated types.
65    Dynamic,
66}
67
68impl NamespaceSerialization {
69    /// Returns `true` if this is [`NamespaceSerialization::None`], `false` otherwise.
70    #[inline]
71    #[must_use]
72    pub fn is_none(&self) -> bool {
73        matches!(self, Self::None)
74    }
75
76    /// Returns `true` if this is [`NamespaceSerialization::Local`],
77    /// [`NamespaceSerialization::Global`], or [`NamespaceSerialization::Dynamic`],
78    /// `false` otherwise.
79    #[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
159/* UnionData */
160
161impl 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
211/* DynamicData */
212
213impl 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
247/* ReferenceData */
248
249impl 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
329/* EnumerationData */
330
331impl 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
407/* SimpleData */
408
409impl 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
473/* ComplexData */
474
475impl 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}