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#[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
50impl 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
95impl 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
128impl 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
199impl 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
256impl 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}