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#[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<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
147impl 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
196impl 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
232impl 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
311impl 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
370impl 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
433impl 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}