xsd_parser/generator/renderer/quick_xml/
serialize.rs

1use proc_macro2::{Ident as Ident2, Literal, TokenStream};
2use quote::{format_ident, quote};
3
4use crate::{
5    code::IdentPath,
6    config::TypedefMode,
7    generator::{
8        data::{
9            ComplexType, ComplexTypeBase, ComplexTypeContent, ComplexTypeElement, ComplexTypeEnum,
10            ComplexTypeStruct, DynamicType, EnumerationType, EnumerationTypeVariant, ReferenceType,
11            TypeData, UnionType, UnionTypeVariant,
12        },
13        misc::Occurs,
14        renderer::Renderer,
15        Config, Context, DynTypeTraits,
16    },
17    schema::Namespace,
18};
19
20/// Implements a [`Renderer`] that renders the code for the `quick_xml` serialization.
21#[derive(Debug)]
22pub struct QuickXmlSerializeRenderer;
23
24impl Renderer for QuickXmlSerializeRenderer {
25    fn initialize(&mut self, config: &mut Config<'_>) {
26        if let DynTypeTraits::Custom(x) = &mut config.dyn_type_traits {
27            let ident = IdentPath::from_parts(
28                [config.xsd_parser_crate.clone(), format_ident!("quick_xml")],
29                format_ident!("WithBoxedSerializer"),
30            );
31
32            if !x.contains(&ident) {
33                x.push(ident);
34            }
35        }
36    }
37
38    fn render_type(&mut self, ctx: &mut Context<'_, '_>, ty: &TypeData<'_>) {
39        match ty {
40            TypeData::BuildIn(_) => (),
41            TypeData::Union(x) => x.render_serializer(ctx),
42            TypeData::Dynamic(x) => x.render_serializer(ctx),
43            TypeData::Reference(x) => x.render_serializer(ctx),
44            TypeData::Enumeration(x) => x.render_serializer(ctx),
45            TypeData::Complex(x) => x.render_serializer(ctx),
46        }
47    }
48}
49
50/* UnionType */
51
52impl UnionType<'_> {
53    pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
54        let Self {
55            type_ident,
56            variants,
57            ..
58        } = self;
59
60        let xsd_parser = &ctx.xsd_parser_crate;
61        let variants = variants
62            .iter()
63            .map(UnionTypeVariant::render_serializer_variant)
64            .collect::<Vec<_>>();
65
66        let usings = [
67            quote!(std::borrow::Cow),
68            quote!(#xsd_parser::quick_xml::Error),
69            quote!(#xsd_parser::quick_xml::SerializeBytes),
70        ];
71        let code = quote! {
72            impl SerializeBytes for #type_ident {
73                fn serialize_bytes(&self) -> Result<Option<Cow<'_, str>>, Error> {
74                    match self {
75                        #( #variants )*
76                    }
77                }
78            }
79        };
80
81        ctx.module().usings(usings).append(code);
82    }
83}
84
85impl UnionTypeVariant<'_> {
86    fn render_serializer_variant(&self) -> TokenStream {
87        let Self { variant_ident, .. } = self;
88
89        quote! {
90            Self::#variant_ident(x) => x.serialize_bytes(),
91        }
92    }
93}
94
95/* DynamicType */
96
97impl DynamicType<'_> {
98    pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
99        let Self { type_ident, .. } = self;
100
101        let xsd_parser = &ctx.xsd_parser_crate;
102
103        let usings = [
104            quote!(#xsd_parser::quick_xml::Error),
105            quote!(#xsd_parser::quick_xml::WithSerializer),
106            quote!(#xsd_parser::quick_xml::BoxedSerializer),
107        ];
108        let code = quote! {
109            impl WithSerializer for #type_ident {
110                type Serializer<'x> = BoxedSerializer<'x>;
111
112                fn serializer<'ser>(
113                    &'ser self,
114                    name: Option<&'ser str>,
115                    is_root: bool
116                ) -> Result<Self::Serializer<'ser>, Error> {
117                    let _name = name;
118
119                    self.0.serializer(None, is_root)
120                }
121            }
122        };
123
124        ctx.module().usings(usings).append(code);
125    }
126}
127
128/* ReferenceType */
129
130impl ReferenceType<'_> {
131    pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
132        let Self {
133            mode,
134            occurs,
135            type_ident,
136            ..
137        } = self;
138
139        if matches!(mode, TypedefMode::Auto | TypedefMode::Typedef) {
140            return;
141        }
142
143        let xsd_parser = ctx.xsd_parser_crate.clone();
144        let body = match occurs {
145            Occurs::None => return,
146            Occurs::Single => {
147                quote! {
148                    self.0.serialize_bytes()
149                }
150            }
151            Occurs::Optional => {
152                quote! {
153                    if let Some(inner) = &self.0 {
154                        Ok(Some(inner.serialize_bytes()?))
155                    } else {
156                        Ok(None)
157                    }
158                }
159            }
160            Occurs::DynamicList | Occurs::StaticList(_) => {
161                quote! {
162                    if self.0.is_empty() {
163                        return Ok(None);
164                    }
165
166                    let mut data = String::new();
167                    for item in &self.0 {
168                        if let Some(bytes) = item.serialize_bytes()? {
169                            if !data.is_empty() {
170                                data.push(' ');
171                            }
172
173                            data.push_str(&bytes);
174                        }
175                    }
176
177                    Ok(Some(Cow::Owned(data)))
178                }
179            }
180        };
181
182        let usings = [
183            quote!(std::borrow::Cow),
184            quote!(#xsd_parser::quick_xml::Error),
185            quote!(#xsd_parser::quick_xml::SerializeBytes),
186        ];
187        let code = quote! {
188            impl SerializeBytes for #type_ident {
189                fn serialize_bytes(&self) -> Result<Option<Cow<'_, str>>, Error> {
190                    #body
191                }
192            }
193        };
194
195        ctx.module().usings(usings).append(code);
196    }
197}
198
199/* EnumerationType */
200
201impl EnumerationType<'_> {
202    pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
203        let Self {
204            type_ident,
205            variants,
206            ..
207        } = self;
208
209        let xsd_parser = &ctx.xsd_parser_crate;
210        let variants = variants
211            .iter()
212            .map(EnumerationTypeVariant::render_serializer_variant);
213
214        let usings = [
215            quote!(std::borrow::Cow),
216            quote!(#xsd_parser::quick_xml::Error),
217            quote!(#xsd_parser::quick_xml::SerializeBytes),
218        ];
219        let code = quote! {
220            impl SerializeBytes for #type_ident {
221                fn serialize_bytes(&self) -> Result<Option<Cow<'_, str>>, Error> {
222                    match self {
223                        #( #variants )*
224                    }
225                }
226            }
227        };
228
229        ctx.module().usings(usings).append(code);
230    }
231}
232
233impl EnumerationTypeVariant<'_> {
234    fn render_serializer_variant(&self) -> TokenStream {
235        let Self {
236            info,
237            target_type,
238            variant_ident,
239        } = self;
240
241        if target_type.is_some() {
242            quote! {
243                Self::#variant_ident(x) => x.serialize_bytes(),
244            }
245        } else {
246            let name = info.ident.name.to_string();
247            let name = Literal::string(&name);
248
249            quote! {
250                Self::#variant_ident => Ok(Some(Cow::Borrowed(#name))),
251            }
252        }
253    }
254}
255
256/* ComplexType */
257
258impl ComplexType<'_> {
259    pub(crate) fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
260        match self {
261            Self::Enum {
262                type_,
263                content_type,
264            } => {
265                type_.render_serializer(ctx);
266
267                if let Some(content_type) = content_type {
268                    content_type.render_serializer(ctx);
269                }
270            }
271            Self::Struct {
272                type_,
273                content_type,
274            } => {
275                type_.render_serializer(ctx);
276
277                if let Some(content_type) = content_type {
278                    content_type.render_serializer(ctx);
279                }
280            }
281        }
282    }
283}
284
285impl ComplexTypeBase {
286    fn render_with_serializer(&self, ctx: &mut Context<'_, '_>) {
287        let Self {
288            type_ident,
289            serializer_ident,
290            ..
291        } = self;
292        let xsd_parser = &ctx.xsd_parser_crate;
293
294        let body = if let Some(tag_name) = &self.element_tag() {
295            self.render_with_serializer_for_element(tag_name)
296        } else {
297            self.render_with_serializer_for_content()
298        };
299
300        let usings = [
301            quote!(#xsd_parser::quick_xml::Error),
302            quote!(#xsd_parser::quick_xml::WithSerializer),
303        ];
304        let code = quote! {
305            impl WithSerializer for #type_ident {
306                type Serializer<'x> = quick_xml_serialize::#serializer_ident<'x>;
307
308                fn serializer<'ser>(
309                    &'ser self,
310                    name: Option<&'ser str>,
311                    is_root: bool
312                ) -> Result<Self::Serializer<'ser>, Error> {
313                    #body
314                }
315            }
316        };
317
318        ctx.module().usings(usings).append(code);
319    }
320
321    fn render_with_serializer_for_element(&self, tag_name: &str) -> TokenStream {
322        let Self {
323            serializer_ident,
324            serializer_state_ident,
325            ..
326        } = self;
327
328        quote! {
329            Ok(quick_xml_serialize::#serializer_ident {
330                value: self,
331                state: Box::new(quick_xml_serialize::#serializer_state_ident::Init__),
332                name: name.unwrap_or(#tag_name),
333                is_root,
334            })
335        }
336    }
337
338    fn render_with_serializer_for_content(&self) -> TokenStream {
339        let Self {
340            serializer_ident,
341            serializer_state_ident,
342            ..
343        } = self;
344
345        quote! {
346            let _name = name;
347            let _is_root = is_root;
348
349            Ok(quick_xml_serialize::#serializer_ident {
350                value: self,
351                state: Box::new(quick_xml_serialize::#serializer_state_ident::Init__),
352            })
353        }
354    }
355
356    fn render_serializer_type(&self, ctx: &mut Context<'_, '_>) {
357        let Self {
358            type_ident,
359            serializer_ident,
360            serializer_state_ident,
361            ..
362        } = self;
363        let extra = self.represents_element().then(|| {
364            quote! {
365                pub(super) name: &'ser str,
366                pub(super) is_root: bool,
367            }
368        });
369
370        let code = quote! {
371            #[derive(Debug)]
372            pub struct #serializer_ident<'ser> {
373                pub(super) value: &'ser super::#type_ident,
374                pub(super) state: Box<#serializer_state_ident<'ser>>,
375                #extra
376            }
377        };
378
379        ctx.quick_xml_serialize().append(code);
380    }
381
382    fn render_serializer_handle_state_end(&self, ctx: &Context<'_, '_>) -> TokenStream {
383        let xsd_parser = &ctx.xsd_parser_crate;
384        let serializer_state_ident = &self.serializer_state_ident;
385
386        ctx.add_quick_xml_serialize_usings([quote!(#xsd_parser::quick_xml::BytesEnd)]);
387
388        quote! {
389            #serializer_state_ident::End__ => {
390                *self.state = #serializer_state_ident::Done__;
391
392                return Ok(Some(
393                    Event::End(
394                        BytesEnd::new(self.name))
395                    )
396                );
397            }
398        }
399    }
400
401    fn render_serializer_xmlns(&self, ctx: &Context<'_, '_>) -> Vec<TokenStream> {
402        let _self = self;
403
404        ctx.types
405            .modules
406            .values()
407            .filter_map(|module| {
408                let ns = module.namespace.as_ref()?;
409                if *ns == Namespace::XS || *ns == Namespace::XML {
410                    return None;
411                }
412
413                let name = module.name.as_ref()?;
414                let ns_const = ctx.resolve_type_for_serialize_module(&module.make_ns_const());
415
416                let xmlns = Literal::byte_string(format!("xmlns:{name}").as_bytes());
417
418                Some(quote! {
419                    bytes.push_attribute((&#xmlns[..], &#ns_const[..]));
420                })
421            })
422            .collect::<Vec<_>>()
423    }
424}
425
426impl ComplexTypeEnum<'_> {
427    fn serializer_need_end_state(&self) -> bool {
428        self.represents_element()
429    }
430
431    fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
432        self.render_with_serializer(ctx);
433        self.render_serializer_type(ctx);
434        self.render_serializer_state_type(ctx);
435        self.render_serializer_impl(ctx);
436    }
437
438    fn render_serializer_state_type(&self, ctx: &mut Context<'_, '_>) {
439        let serializer_state_ident = &self.serializer_state_ident;
440
441        let state_variants = self
442            .elements
443            .iter()
444            .map(|x| x.render_serializer_state_variant(ctx));
445        let state_end = self.represents_element().then(|| {
446            quote! {
447                End__,
448            }
449        });
450
451        let code = quote! {
452            #[derive(Debug)]
453            pub(super) enum #serializer_state_ident<'ser> {
454                Init__,
455                #( #state_variants )*
456                #state_end
457                Done__,
458                Phantom__(&'ser ()),
459            }
460        };
461
462        ctx.quick_xml_serialize().append(code);
463    }
464
465    fn render_serializer_impl(&self, ctx: &mut Context<'_, '_>) {
466        let serializer_ident = &self.serializer_ident;
467        let serializer_state_ident = &self.serializer_state_ident;
468        let xsd_parser = &ctx.xsd_parser_crate;
469
470        let emit_start_event = self
471            .serializer_need_end_state()
472            .then(|| self.render_serializer_impl_start_event(ctx));
473
474        let final_state = if self.serializer_need_end_state() {
475            quote!(#serializer_state_ident::End__)
476        } else {
477            quote!(#serializer_state_ident::Done__)
478        };
479
480        let variants_init = self.elements.iter().map(|element| {
481            let type_ident = &self.type_ident;
482            let variant_ident = &element.variant_ident;
483            let init = element.render_serializer_enum_state_init(ctx, &self.serializer_state_ident);
484
485            quote! {
486                super::#type_ident::#variant_ident(x) => #init,
487            }
488        });
489
490        let handle_state_init = quote! {
491            match self.value {
492                #( #variants_init )*
493            }
494        };
495
496        let handle_state_variants = self.elements.iter().map(|element| {
497            let variant_ident = &element.variant_ident;
498
499            quote! {
500                #serializer_state_ident::#variant_ident(x) => {
501                    match x.next().transpose()? {
502                        Some(event) => return Ok(Some(event)),
503                        None => *self.state = #final_state,
504                    }
505                }
506            }
507        });
508
509        let handle_state_end = self
510            .serializer_need_end_state()
511            .then(|| self.render_serializer_handle_state_end(ctx));
512
513        let usings = [
514            quote!(core::iter::Iterator),
515            quote!(#xsd_parser::quick_xml::Event),
516            quote!(#xsd_parser::quick_xml::Error),
517        ];
518        let code = quote! {
519            impl<'ser> #serializer_ident<'ser> {
520                fn next_event(&mut self) -> Result<Option<Event<'ser>>, Error> {
521                    loop {
522                        match &mut *self.state {
523                            #serializer_state_ident::Init__ => {
524                                #handle_state_init
525                                #emit_start_event
526                            }
527                            #( #handle_state_variants )*
528                            #handle_state_end
529                            #serializer_state_ident::Done__ => return Ok(None),
530                            #serializer_state_ident::Phantom__(_) => unreachable!(),
531                        }
532                    }
533                }
534            }
535
536            impl<'ser> Iterator for #serializer_ident<'ser> {
537                type Item = Result<Event<'ser>, Error>;
538
539                fn next(&mut self) -> Option<Self::Item> {
540                    match self.next_event() {
541                        Ok(Some(event)) => Some(Ok(event)),
542                        Ok(None) => None,
543                        Err(error) => {
544                            *self.state = #serializer_state_ident::Done__;
545
546                            Some(Err(error))
547                        }
548                    }
549                }
550            }
551        };
552
553        ctx.quick_xml_serialize().usings(usings).append(code);
554    }
555
556    fn render_serializer_impl_start_event(&self, ctx: &Context<'_, '_>) -> TokenStream {
557        let xsd_parser = &ctx.xsd_parser_crate;
558        ctx.add_quick_xml_serialize_usings([quote!(#xsd_parser::quick_xml::BytesStart)]);
559
560        let xmlns = self.render_serializer_xmlns(ctx);
561        let bytes_ctor = if xmlns.is_empty() {
562            quote! {
563                let bytes = BytesStart::new(self.name);
564            }
565        } else {
566            quote! {
567                let mut bytes = BytesStart::new(self.name);
568                if self.is_root {
569                    #( #xmlns )*
570                }
571            }
572        };
573
574        quote! {
575            #bytes_ctor
576            return Ok(Some(Event::Start(bytes)))
577        }
578    }
579}
580
581impl ComplexTypeStruct<'_> {
582    fn serializer_need_end_state(&self) -> bool {
583        self.represents_element() && self.has_content()
584    }
585
586    fn render_serializer(&self, ctx: &mut Context<'_, '_>) {
587        self.render_with_serializer(ctx);
588        self.render_serializer_type(ctx);
589        self.render_serializer_state_type(ctx);
590        self.render_serializer_impl(ctx);
591    }
592
593    fn render_serializer_state_type(&self, ctx: &mut Context<'_, '_>) {
594        let state_ident = &self.serializer_state_ident;
595
596        let state_variants = self
597            .elements()
598            .iter()
599            .map(|x| x.render_serializer_state_variant(ctx));
600        let state_content = self
601            .content()
602            .map(|x| x.render_serializer_state_variant(ctx));
603        let state_end = self.serializer_need_end_state().then(|| {
604            quote! {
605                End__,
606            }
607        });
608
609        let code = quote! {
610            #[derive(Debug)]
611            pub(super) enum #state_ident<'ser> {
612                Init__,
613                #( #state_variants )*
614                #state_content
615                #state_end
616                Done__,
617                Phantom__(&'ser ()),
618            }
619        };
620
621        ctx.quick_xml_serialize().append(code);
622    }
623
624    #[allow(clippy::too_many_lines)]
625    fn render_serializer_impl(&self, ctx: &mut Context<'_, '_>) {
626        let xsd_parser = &ctx.xsd_parser_crate;
627        let serializer_ident = &self.serializer_ident;
628        let serializer_state_ident = &self.serializer_state_ident;
629
630        let emit_start_event = self
631            .represents_element()
632            .then(|| self.render_serializer_impl_start_event(ctx));
633
634        let final_state = if self.serializer_need_end_state() {
635            quote!(#serializer_state_ident::End__)
636        } else {
637            quote!(#serializer_state_ident::Done__)
638        };
639
640        let elements = self.elements();
641        let handle_state_init = if let Some(first) = elements.first() {
642            let init = first.render_serializer_struct_state_init(ctx, serializer_state_ident);
643
644            quote!(#init;)
645        } else if let Some(content) = &self.content() {
646            let init = content.render_serializer_state_init(ctx, serializer_state_ident);
647
648            quote!(#init;)
649        } else {
650            quote!(*self.state = #final_state;)
651        };
652
653        let handle_state_variants = (0..).take(elements.len()).map(|i| {
654            let element = &elements[i];
655            let variant_ident = &element.variant_ident;
656
657            let next = if let Some(next) = elements.get(i + 1) {
658                let init = next.render_serializer_struct_state_init(ctx, serializer_state_ident);
659
660                quote!(#init,)
661            } else {
662                quote! {
663                    *self.state = #final_state,
664                }
665            };
666
667            quote! {
668                #serializer_state_ident::#variant_ident(x) => match x.next().transpose()? {
669                    Some(event) => return Ok(Some(event)),
670                    None => #next
671                }
672            }
673        });
674
675        let handle_state_content = self.content().map(|_| {
676            quote! {
677                #serializer_state_ident::Content__(x) => match x.next().transpose()? {
678                    Some(event) => return Ok(Some(event)),
679                    None => *self.state = #final_state,
680                }
681            }
682        });
683
684        let handle_state_end = self
685            .serializer_need_end_state()
686            .then(|| self.render_serializer_handle_state_end(ctx));
687
688        let usings = [
689            quote!(core::iter::Iterator),
690            quote!(#xsd_parser::quick_xml::Event),
691            quote!(#xsd_parser::quick_xml::Error),
692        ];
693        let code = quote! {
694            impl<'ser> #serializer_ident<'ser> {
695                fn next_event(&mut self) -> Result<Option<Event<'ser>>, Error>
696                {
697                    loop {
698                        match &mut *self.state {
699                            #serializer_state_ident::Init__ => {
700                                #handle_state_init
701                                #emit_start_event
702                            }
703                            #( #handle_state_variants )*
704                            #handle_state_content
705                            #handle_state_end
706                            #serializer_state_ident::Done__ => return Ok(None),
707                            #serializer_state_ident::Phantom__(_) => unreachable!(),
708                        }
709                    }
710                }
711            }
712
713            impl<'ser> Iterator for #serializer_ident<'ser> {
714                type Item = Result<Event<'ser>, Error>;
715
716                fn next(&mut self) -> Option<Self::Item> {
717                    match self.next_event() {
718                        Ok(Some(event)) => Some(Ok(event)),
719                        Ok(None) => None,
720                        Err(error) => {
721                            *self.state = #serializer_state_ident::Done__;
722
723                            Some(Err(error))
724                        }
725                    }
726                }
727            }
728        };
729
730        ctx.quick_xml_serialize().usings(usings).append(code);
731    }
732
733    fn render_serializer_impl_start_event(&self, ctx: &Context<'_, '_>) -> TokenStream {
734        let xsd_parser = &ctx.xsd_parser_crate;
735
736        let xmlns = self.render_serializer_xmlns(ctx);
737        let attributes = self.attributes.iter().map(|attrib| {
738            let attrib_name = &attrib.tag_name;
739            let field_ident = &attrib.ident;
740
741            if attrib.is_option {
742                ctx.add_quick_xml_serialize_usings([
743                    quote!(#xsd_parser::quick_xml::write_attrib_opt),
744                ]);
745
746                quote! {
747                    write_attrib_opt(&mut bytes, #attrib_name, &self.value.#field_ident)?;
748                }
749            } else {
750                ctx.add_quick_xml_serialize_usings([quote!(#xsd_parser::quick_xml::write_attrib)]);
751
752                quote! {
753                    write_attrib(&mut bytes, #attrib_name, &self.value.#field_ident)?;
754                }
755            }
756        });
757
758        ctx.add_quick_xml_serialize_usings([
759            quote!(#xsd_parser::quick_xml::Event),
760            quote!(#xsd_parser::quick_xml::BytesStart),
761        ]);
762
763        let bytes_mut = self.has_attributes().then(|| quote!(mut));
764        let bytes_ctor = if xmlns.is_empty() {
765            quote! {
766                let #bytes_mut bytes = BytesStart::new(self.name);
767            }
768        } else {
769            quote! {
770                let mut bytes = BytesStart::new(self.name);
771                if self.is_root {
772                    #( #xmlns )*
773                }
774            }
775        };
776
777        let event = if self.has_content() {
778            format_ident!("Start")
779        } else {
780            format_ident!("Empty")
781        };
782
783        quote! {
784            #bytes_ctor
785            #( #attributes )*
786            return Ok(Some(Event::#event(bytes)))
787        }
788    }
789}
790
791impl ComplexTypeContent {
792    fn render_serializer_state_variant(&self, ctx: &Context<'_, '_>) -> Option<TokenStream> {
793        let serializer = self
794            .occurs
795            .make_serializer_type(&ctx.resolve_type_for_serialize_module(&self.target_type))?;
796
797        Some(quote! {
798            Content__(#serializer),
799        })
800    }
801
802    fn render_serializer_state_init(
803        &self,
804        ctx: &Context<'_, '_>,
805        state_ident: &Ident2,
806    ) -> TokenStream {
807        let xsd_parser = &ctx.xsd_parser_crate;
808
809        match self.occurs {
810            Occurs::None => crate::unreachable!(),
811            Occurs::Single => {
812                ctx.add_quick_xml_serialize_usings([
813                    quote!(#xsd_parser::quick_xml::WithSerializer),
814                ]);
815
816                quote! {
817                    *self.state = #state_ident::Content__(
818                        WithSerializer::serializer(&self.value.content, None, false)?
819                    )
820                }
821            }
822            Occurs::Optional => {
823                ctx.add_quick_xml_serialize_usings([
824                    quote!(#xsd_parser::quick_xml::IterSerializer),
825                ]);
826
827                quote! {
828                    *self.state = #state_ident::Content__(
829                        IterSerializer::new(
830                            self.value.content.as_ref(),
831                            None,
832                            false
833                        )
834                    )
835                }
836            }
837            Occurs::DynamicList | Occurs::StaticList(_) => {
838                ctx.add_quick_xml_serialize_usings([
839                    quote!(#xsd_parser::quick_xml::IterSerializer),
840                ]);
841
842                quote! {
843                    *self.state = #state_ident::Content__(
844                        IterSerializer::new(
845                            &self.value.content[..],
846                            None,
847                            false
848                        )
849                    )
850                }
851            }
852        }
853    }
854}
855
856impl ComplexTypeElement<'_> {
857    fn render_serializer_state_variant(&self, ctx: &Context<'_, '_>) -> TokenStream {
858        let target_type = ctx.resolve_type_for_serialize_module(&self.target_type);
859        let variant_ident = &self.variant_ident;
860
861        let serializer = self.occurs.make_serializer_type(&target_type);
862
863        quote! {
864            #variant_ident(#serializer),
865        }
866    }
867
868    fn render_serializer_enum_state_init(
869        &self,
870        ctx: &Context<'_, '_>,
871        state_ident: &Ident2,
872    ) -> TokenStream {
873        let value = match self.occurs {
874            Occurs::None => unreachable!(),
875            Occurs::Single if self.need_indirection => quote!(&**x),
876            Occurs::Single => quote!(x),
877            Occurs::Optional if self.need_indirection => quote!(x.as_ref().map(|x| &**x)),
878            Occurs::Optional => quote!(x.as_ref()),
879            Occurs::DynamicList | Occurs::StaticList(_) => quote!(&x[..]),
880        };
881
882        self.render_serializer_state_init(ctx, state_ident, &value)
883    }
884
885    fn render_serializer_struct_state_init(
886        &self,
887        ctx: &Context<'_, '_>,
888        state_ident: &Ident2,
889    ) -> TokenStream {
890        let field_ident = &self.field_ident;
891
892        let value = match self.occurs {
893            Occurs::None => unreachable!(),
894            Occurs::Single if self.need_indirection => quote!(&*self.value.#field_ident),
895            Occurs::Single => quote!(&self.value.#field_ident),
896            Occurs::Optional if self.need_indirection => {
897                quote!(self.value.#field_ident.as_ref().map(|x| &**x))
898            }
899            Occurs::Optional => quote!(self.value.#field_ident.as_ref()),
900            Occurs::DynamicList | Occurs::StaticList(_) => quote!(&self.value.#field_ident[..]),
901        };
902
903        self.render_serializer_state_init(ctx, state_ident, &value)
904    }
905
906    fn render_serializer_state_init(
907        &self,
908        ctx: &Context<'_, '_>,
909        state_ident: &Ident2,
910        value: &TokenStream,
911    ) -> TokenStream {
912        let xsd_parser = &ctx.xsd_parser_crate;
913
914        let field_name = &self.tag_name;
915        let variant_ident = &self.variant_ident;
916
917        match self.occurs {
918            Occurs::None => crate::unreachable!(),
919            Occurs::Single => {
920                ctx.add_quick_xml_serialize_usings([
921                    quote!(#xsd_parser::quick_xml::WithSerializer),
922                ]);
923
924                quote! {
925                    *self.state = #state_ident::#variant_ident(
926                        WithSerializer::serializer(#value, Some(#field_name), false)?
927                    )
928                }
929            }
930            Occurs::Optional | Occurs::DynamicList | Occurs::StaticList(_) => {
931                ctx.add_quick_xml_serialize_usings([
932                    quote!(#xsd_parser::quick_xml::IterSerializer),
933                ]);
934
935                quote! {
936                    *self.state = #state_ident::#variant_ident(
937                        IterSerializer::new(
938                            #value,
939                            Some(#field_name),
940                            false
941                        )
942                    )
943                }
944            }
945        }
946    }
947}
948
949impl Occurs {
950    fn make_serializer_type(&self, target_type: &TokenStream) -> Option<TokenStream> {
951        match self {
952            Occurs::None => None,
953            Occurs::Single => Some(quote!(<#target_type as WithSerializer>::Serializer<'ser>)),
954            Occurs::Optional => {
955                Some(quote!(IterSerializer<'ser, Option<&'ser #target_type>, #target_type>))
956            }
957            Occurs::DynamicList | Occurs::StaticList(..) => {
958                Some(quote!(IterSerializer<'ser, &'ser [#target_type], #target_type>))
959            }
960        }
961    }
962}