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