xsd_parser/pipeline/renderer/steps/quick_xml/
serialize.rs

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