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