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#[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
45impl 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
90impl 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
123impl 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
194impl 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
249impl 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}