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