1use std::collections::HashMap;
10
11use proc_macro2::{Span, TokenStream};
12use quote::{quote, ToTokens};
13use syn::*;
14
15use crate::common::{AsXmlParts, FromXmlParts, ItemDef};
16use crate::compound::Compound;
17use crate::error_message::ParentRef;
18use crate::meta::{reject_key, Flag, NameRef, NamespaceRef, QNameRef, XmlCompoundMeta};
19use crate::state::{AsItemsStateMachine, FromEventsMatchMode, FromEventsStateMachine};
20use crate::structs::StructInner;
21use crate::types::{ref_ty, ty_from_ident};
22
23struct NameVariant {
26 name: NameRef,
28
29 ident: Ident,
31
32 inner: Compound,
34}
35
36impl NameVariant {
37 fn new(decl: &Variant, enum_namespace: &NamespaceRef) -> Result<Self> {
39 let XmlCompoundMeta {
43 span: meta_span,
44 qname: QNameRef { namespace, name },
45 exhaustive,
46 debug,
47 builder,
48 iterator,
49 on_unknown_attribute,
50 on_unknown_child,
51 transparent,
52 discard,
53 deserialize_callback,
54 attribute,
55 value,
56 } = XmlCompoundMeta::parse_from_attributes(&decl.attrs)?;
57
58 reject_key!(debug flag not on "enum variants" only on "enums and structs");
59 reject_key!(exhaustive flag not on "enum variants" only on "enums");
60 reject_key!(namespace not on "enum variants" only on "enums and structs");
61 reject_key!(builder not on "enum variants" only on "enums and structs");
62 reject_key!(iterator not on "enum variants" only on "enums and structs");
63 reject_key!(transparent flag not on "named enum variants" only on "structs");
64 reject_key!(deserialize_callback not on "enum variants" only on "enums and structs");
65 reject_key!(attribute not on "enum variants" only on "attribute-switched enums");
66 reject_key!(value not on "name-switched enum variants" only on "attribute-switched enum variants");
67
68 let Some(name) = name else {
69 return Err(Error::new(
70 meta_span,
71 "`name` is required on name-switched enum variants",
72 ));
73 };
74
75 Ok(Self {
76 name,
77 ident: decl.ident.clone(),
78 inner: Compound::from_fields(
79 &decl.fields,
80 enum_namespace,
81 on_unknown_attribute,
82 on_unknown_child,
83 discard,
84 )?,
85 })
86 }
87
88 fn make_from_events_statemachine(
89 &self,
90 enum_ident: &Ident,
91 state_ty_ident: &Ident,
92 ) -> Result<FromEventsStateMachine> {
93 let xml_name = &self.name;
94
95 Ok(self
96 .inner
97 .make_from_events_statemachine(
98 state_ty_ident,
99 &ParentRef::Named(Path {
100 leading_colon: None,
101 segments: [
102 PathSegment::from(enum_ident.clone()),
103 self.ident.clone().into(),
104 ]
105 .into_iter()
106 .collect(),
107 }),
108 &self.ident.to_string(),
109 )?
110 .with_augmented_init(|init| {
111 quote! {
112 if name.1 != #xml_name {
113 ::core::result::Result::Err(::xso::error::FromEventsError::Mismatch {
114 name,
115 attrs,
116 })
117 } else {
118 #init
119 }
120 }
121 })
122 .compile())
123 }
124
125 fn make_as_item_iter_statemachine(
126 &self,
127 xml_namespace: &NamespaceRef,
128 enum_ident: &Ident,
129 state_ty_ident: &Ident,
130 item_iter_ty_lifetime: &Lifetime,
131 ) -> Result<AsItemsStateMachine> {
132 let xml_name = &self.name;
133
134 Ok(self
135 .inner
136 .make_as_item_iter_statemachine(
137 &ParentRef::Named(Path {
138 leading_colon: None,
139 segments: [
140 PathSegment::from(enum_ident.clone()),
141 self.ident.clone().into(),
142 ]
143 .into_iter()
144 .collect(),
145 }),
146 state_ty_ident,
147 &self.ident.to_string(),
148 item_iter_ty_lifetime,
149 )?
150 .with_augmented_init(|init| {
151 quote! {
152 let name = (
153 ::xso::exports::rxml::Namespace::from(#xml_namespace),
154 ::xso::exports::alloc::borrow::Cow::Borrowed(#xml_name),
155 );
156 #init
157 }
158 })
159 .compile())
160 }
161}
162
163struct NameSwitchedEnum {
166 namespace: NamespaceRef,
168
169 variants: Vec<NameVariant>,
171
172 exhaustive: bool,
174}
175
176impl NameSwitchedEnum {
177 fn new<'x, I: IntoIterator<Item = &'x Variant>>(
178 namespace: NamespaceRef,
179 exhaustive: Flag,
180 variant_iter: I,
181 ) -> Result<Self> {
182 let mut variants = Vec::new();
183 let mut seen_names = HashMap::new();
184 for variant in variant_iter {
185 let variant = NameVariant::new(variant, &namespace)?;
186 if let Some(other) = seen_names.get(&variant.name) {
187 return Err(Error::new_spanned(
188 variant.name,
189 format!(
190 "duplicate `name` in enum: variants {} and {} have the same XML name",
191 other, variant.ident
192 ),
193 ));
194 }
195 seen_names.insert(variant.name.clone(), variant.ident.clone());
196 variants.push(variant);
197 }
198
199 Ok(Self {
200 namespace,
201 variants,
202 exhaustive: exhaustive.is_set(),
203 })
204 }
205
206 fn make_from_events_statemachine(
208 &self,
209 target_ty_ident: &Ident,
210 state_ty_ident: &Ident,
211 ) -> Result<FromEventsStateMachine> {
212 let xml_namespace = &self.namespace;
213
214 let mut statemachine = FromEventsStateMachine::new();
215 for variant in self.variants.iter() {
216 statemachine
217 .merge(variant.make_from_events_statemachine(target_ty_ident, state_ty_ident)?);
218 }
219
220 statemachine.set_pre_init(quote! {
221 if name.0 != #xml_namespace {
222 return ::core::result::Result::Err(::xso::error::FromEventsError::Mismatch {
223 name,
224 attrs,
225 })
226 }
227 });
228
229 if self.exhaustive {
230 let mismatch_err = format!("This is not a {} element.", target_ty_ident);
231 statemachine.set_fallback(quote! {
232 ::core::result::Result::Err(::xso::error::FromEventsError::Invalid(
233 ::xso::error::Error::Other(#mismatch_err),
234 ))
235 })
236 }
237
238 Ok(statemachine)
239 }
240
241 fn make_as_item_iter_statemachine(
243 &self,
244 target_ty_ident: &Ident,
245 state_ty_ident: &Ident,
246 item_iter_ty_lifetime: &Lifetime,
247 ) -> Result<AsItemsStateMachine> {
248 let mut statemachine = AsItemsStateMachine::new();
249 for variant in self.variants.iter() {
250 statemachine.merge(variant.make_as_item_iter_statemachine(
251 &self.namespace,
252 target_ty_ident,
253 state_ty_ident,
254 item_iter_ty_lifetime,
255 )?);
256 }
257
258 Ok(statemachine)
259 }
260}
261
262struct ValueVariant {
265 value: String,
267
268 ident: Ident,
270
271 inner: Compound,
273}
274
275impl ValueVariant {
276 fn new(decl: &Variant, enum_namespace: &NamespaceRef) -> Result<Self> {
278 let XmlCompoundMeta {
282 span: meta_span,
283 qname: QNameRef { namespace, name },
284 exhaustive,
285 debug,
286 builder,
287 iterator,
288 on_unknown_attribute,
289 on_unknown_child,
290 transparent,
291 discard,
292 deserialize_callback,
293 attribute,
294 value,
295 } = XmlCompoundMeta::parse_from_attributes(&decl.attrs)?;
296
297 reject_key!(debug flag not on "enum variants" only on "enums and structs");
298 reject_key!(exhaustive flag not on "enum variants" only on "enums");
299 reject_key!(namespace not on "enum variants" only on "enums and structs");
300 reject_key!(name not on "attribute-switched enum variants" only on "enums, structs and name-switched enum variants");
301 reject_key!(builder not on "enum variants" only on "enums and structs");
302 reject_key!(iterator not on "enum variants" only on "enums and structs");
303 reject_key!(transparent flag not on "named enum variants" only on "structs");
304 reject_key!(deserialize_callback not on "enum variants" only on "enums and structs");
305 reject_key!(attribute not on "enum variants" only on "attribute-switched enums");
306
307 let Some(value) = value else {
308 return Err(Error::new(
309 meta_span,
310 "`value` is required on attribute-switched enum variants",
311 ));
312 };
313
314 Ok(Self {
315 value: value.value(),
316 ident: decl.ident.clone(),
317 inner: Compound::from_fields(
318 &decl.fields,
319 enum_namespace,
320 on_unknown_attribute,
321 on_unknown_child,
322 discard,
323 )?,
324 })
325 }
326
327 fn make_from_events_statemachine(
328 &self,
329 enum_ident: &Ident,
330 state_ty_ident: &Ident,
331 ) -> Result<FromEventsStateMachine> {
332 let value = &self.value;
333
334 Ok(self
335 .inner
336 .make_from_events_statemachine(
337 state_ty_ident,
338 &ParentRef::Named(Path {
339 leading_colon: None,
340 segments: [
341 PathSegment::from(enum_ident.clone()),
342 self.ident.clone().into(),
343 ]
344 .into_iter()
345 .collect(),
346 }),
347 &self.ident.to_string(),
348 )?
349 .with_augmented_init(|init| {
350 quote! {
351 #value => { #init },
352 }
353 })
354 .compile())
355 }
356
357 fn make_as_item_iter_statemachine(
358 &self,
359 elem_namespace: &NamespaceRef,
360 elem_name: &NameRef,
361 attr_namespace: &TokenStream,
362 attr_name: &NameRef,
363 enum_ident: &Ident,
364 state_ty_ident: &Ident,
365 item_iter_ty_lifetime: &Lifetime,
366 ) -> Result<AsItemsStateMachine> {
367 let attr_value = &self.value;
368
369 Ok(self
370 .inner
371 .make_as_item_iter_statemachine(
372 &ParentRef::Named(Path {
373 leading_colon: None,
374 segments: [
375 PathSegment::from(enum_ident.clone()),
376 self.ident.clone().into(),
377 ]
378 .into_iter()
379 .collect(),
380 }),
381 state_ty_ident,
382 &self.ident.to_string(),
383 item_iter_ty_lifetime,
384 )?
385 .with_augmented_init(|init| {
386 quote! {
387 let name = (
388 ::xso::exports::rxml::Namespace::from(#elem_namespace),
389 ::xso::exports::alloc::borrow::Cow::Borrowed(#elem_name),
390 );
391 #init
392 }
393 })
394 .with_extra_header_state(
395 quote::format_ident!("{}Discriminator", &self.ident.to_string()),
398 quote! {
399 ::xso::Item::Attribute(
400 #attr_namespace,
401 ::xso::exports::alloc::borrow::Cow::Borrowed(#attr_name),
402 ::xso::exports::alloc::borrow::Cow::Borrowed(#attr_value),
403 )
404 },
405 )
406 .compile())
407 }
408}
409
410struct AttributeSwitchedEnum {
413 elem_namespace: NamespaceRef,
415
416 elem_name: NameRef,
418
419 attr_namespace: Option<NamespaceRef>,
422
423 attr_name: NameRef,
425
426 variants: Vec<ValueVariant>,
428}
429
430impl AttributeSwitchedEnum {
431 fn new<'x, I: IntoIterator<Item = &'x Variant>>(
432 elem_namespace: NamespaceRef,
433 elem_name: NameRef,
434 attr_namespace: Option<NamespaceRef>,
435 attr_name: NameRef,
436 variant_iter: I,
437 ) -> Result<Self> {
438 let mut variants = Vec::new();
439 let mut seen_values = HashMap::new();
440 for variant in variant_iter {
441 let variant = ValueVariant::new(variant, &elem_namespace)?;
442 if let Some(other) = seen_values.get(&variant.value) {
443 return Err(Error::new_spanned(
444 variant.value,
445 format!(
446 "duplicate `value` in enum: variants {} and {} have the same attribute value",
447 other, variant.ident
448 ),
449 ));
450 }
451 seen_values.insert(variant.value.clone(), variant.ident.clone());
452 variants.push(variant);
453 }
454
455 Ok(Self {
456 elem_namespace,
457 elem_name,
458 attr_namespace,
459 attr_name,
460 variants,
461 })
462 }
463
464 fn make_from_events_statemachine(
466 &self,
467 target_ty_ident: &Ident,
468 state_ty_ident: &Ident,
469 ) -> Result<FromEventsStateMachine> {
470 let elem_namespace = &self.elem_namespace;
471 let elem_name = &self.elem_name;
472 let attr_namespace = match self.attr_namespace.as_ref() {
473 Some(v) => v.to_token_stream(),
474 None => quote! {
475 ::xso::exports::rxml::Namespace::none()
476 },
477 };
478 let attr_name = &self.attr_name;
479
480 let mut statemachine = FromEventsStateMachine::new();
481 for variant in self.variants.iter() {
482 statemachine
483 .merge(variant.make_from_events_statemachine(target_ty_ident, state_ty_ident)?);
484 }
485
486 statemachine.set_pre_init(quote! {
487 let attr = {
488 if name.0 != #elem_namespace || name.1 != #elem_name {
489 return ::core::result::Result::Err(
490 ::xso::error::FromEventsError::Mismatch {
491 name,
492 attrs,
493 },
494 );
495 }
496
497 let ::core::option::Option::Some(attr) = attrs.remove(#attr_namespace, #attr_name) else {
498 return ::core::result::Result::Err(
499 ::xso::error::FromEventsError::Invalid(
500 ::xso::error::Error::Other("Missing discriminator attribute.")
501 ),
502 );
503 };
504
505 attr
506 };
507 });
508 statemachine.set_fallback(quote! {
509 ::core::result::Result::Err(
510 ::xso::error::FromEventsError::Invalid(
511 ::xso::error::Error::Other("Unknown value for discriminator attribute.")
512 ),
513 )
514 });
515 statemachine.set_match_mode(FromEventsMatchMode::Matched {
516 expr: quote! { attr.as_str() },
517 });
518
519 Ok(statemachine)
520 }
521
522 fn make_as_item_iter_statemachine(
524 &self,
525 target_ty_ident: &Ident,
526 state_ty_ident: &Ident,
527 item_iter_ty_lifetime: &Lifetime,
528 ) -> Result<AsItemsStateMachine> {
529 let attr_namespace = match self.attr_namespace.as_ref() {
530 Some(v) => v.to_token_stream(),
531 None => quote! {
532 ::xso::exports::rxml::Namespace::NONE
533 },
534 };
535
536 let mut statemachine = AsItemsStateMachine::new();
537 for variant in self.variants.iter() {
538 statemachine.merge(variant.make_as_item_iter_statemachine(
539 &self.elem_namespace,
540 &self.elem_name,
541 &attr_namespace,
542 &self.attr_name,
543 target_ty_ident,
544 state_ty_ident,
545 item_iter_ty_lifetime,
546 )?);
547 }
548
549 Ok(statemachine)
550 }
551}
552
553struct DynamicVariant {
555 ident: Ident,
557
558 inner: StructInner,
560}
561
562impl DynamicVariant {
563 fn new(variant: &Variant) -> Result<Self> {
564 let ident = variant.ident.clone();
565 let meta = XmlCompoundMeta::parse_from_attributes(&variant.attrs)?;
566
567 let XmlCompoundMeta {
571 span: _,
572 qname: _, ref exhaustive,
574 ref debug,
575 ref builder,
576 ref iterator,
577 on_unknown_attribute: _, on_unknown_child: _, transparent: _, discard: _, ref deserialize_callback,
582 ref attribute,
583 ref value,
584 } = meta;
585
586 reject_key!(debug flag not on "enum variants" only on "enums and structs");
587 reject_key!(exhaustive flag not on "enum variants" only on "enums");
588 reject_key!(builder not on "enum variants" only on "enums and structs");
589 reject_key!(iterator not on "enum variants" only on "enums and structs");
590 reject_key!(deserialize_callback not on "enum variants" only on "enums and structs");
591 reject_key!(attribute not on "enum variants" only on "attribute-switched enums");
592 reject_key!(value not on "dynamic enum variants" only on "attribute-switched enum variants");
593
594 let inner = StructInner::new(meta, &variant.fields)?;
595 Ok(Self { ident, inner })
596 }
597}
598
599struct DynamicEnum {
602 variants: Vec<DynamicVariant>,
604}
605
606impl DynamicEnum {
607 fn new<'x, I: IntoIterator<Item = &'x Variant>>(variant_iter: I) -> Result<Self> {
608 let mut variants = Vec::new();
609 for variant in variant_iter {
610 variants.push(DynamicVariant::new(variant)?);
611 }
612
613 Ok(Self { variants })
614 }
615
616 fn make_from_events_statemachine(
618 &self,
619 target_ty_ident: &Ident,
620 state_ty_ident: &Ident,
621 ) -> Result<FromEventsStateMachine> {
622 let mut statemachine = FromEventsStateMachine::new();
623 for variant in self.variants.iter() {
624 let submachine = variant.inner.make_from_events_statemachine(
625 state_ty_ident,
626 &ParentRef::Named(Path {
627 leading_colon: None,
628 segments: [
629 PathSegment::from(target_ty_ident.clone()),
630 variant.ident.clone().into(),
631 ]
632 .into_iter()
633 .collect(),
634 }),
635 &variant.ident.to_string(),
636 )?;
637
638 statemachine.merge(submachine.compile());
639 }
640
641 Ok(statemachine)
642 }
643
644 fn make_as_item_iter_statemachine(
646 &self,
647 target_ty_ident: &Ident,
648 state_ty_ident: &Ident,
649 item_iter_ty_lifetime: &Lifetime,
650 ) -> Result<AsItemsStateMachine> {
651 let mut statemachine = AsItemsStateMachine::new();
652 for variant in self.variants.iter() {
653 let submachine = variant.inner.make_as_item_iter_statemachine(
654 &ParentRef::Named(Path {
655 leading_colon: None,
656 segments: [
657 PathSegment::from(target_ty_ident.clone()),
658 variant.ident.clone().into(),
659 ]
660 .into_iter()
661 .collect(),
662 }),
663 state_ty_ident,
664 &variant.ident.to_string(),
665 item_iter_ty_lifetime,
666 )?;
667
668 statemachine.merge(submachine.compile());
669 }
670
671 Ok(statemachine)
672 }
673}
674
675enum EnumInner {
677 NameSwitched(NameSwitchedEnum),
680
681 AttributeSwitched(AttributeSwitchedEnum),
684
685 Dynamic(DynamicEnum),
687}
688
689impl EnumInner {
690 fn new<'x, I: IntoIterator<Item = &'x Variant>>(
691 meta: XmlCompoundMeta,
692 variant_iter: I,
693 ) -> Result<Self> {
694 let XmlCompoundMeta {
698 span,
699 qname: QNameRef { namespace, name },
700 exhaustive,
701 debug,
702 builder,
703 iterator,
704 on_unknown_attribute,
705 on_unknown_child,
706 transparent,
707 discard,
708 deserialize_callback,
709 attribute,
710 value,
711 } = meta;
712
713 assert!(builder.is_none());
717 assert!(iterator.is_none());
718 assert!(!debug.is_set());
719 assert!(deserialize_callback.is_none());
720
721 reject_key!(transparent flag not on "enums" only on "structs");
722 reject_key!(on_unknown_attribute not on "enums" only on "enum variants and structs");
723 reject_key!(on_unknown_child not on "enums" only on "enum variants and structs");
724 reject_key!(discard vec not on "enums" only on "enum variants and structs");
725 reject_key!(value not on "enums" only on "attribute-switched enum variants");
726
727 if let Some(attribute) = attribute {
728 let Some(attr_name) = attribute.qname.name else {
729 return Err(Error::new(
730 attribute.span,
731 "missing `name` for `attribute` key",
732 ));
733 };
734
735 let attr_namespace = attribute.qname.namespace;
736
737 let Some(elem_namespace) = namespace else {
738 let mut error =
739 Error::new(span, "missing `namespace` key on attribute-switched enum");
740 error.combine(Error::new(
741 attribute.span,
742 "enum is attribute-switched because of the `attribute` key here",
743 ));
744 return Err(error);
745 };
746
747 let Some(elem_name) = name else {
748 let mut error = Error::new(span, "missing `name` key on attribute-switched enum");
749 error.combine(Error::new(
750 attribute.span,
751 "enum is attribute-switched because of the `attribute` key here",
752 ));
753 return Err(error);
754 };
755
756 if !exhaustive.is_set() {
757 return Err(Error::new(
758 span,
759 "attribute-switched enums must be marked as `exhaustive`. non-exhaustive attribute-switched enums are not supported."
760 ));
761 }
762
763 Ok(Self::AttributeSwitched(AttributeSwitchedEnum::new(
764 elem_namespace,
765 elem_name,
766 attr_namespace,
767 attr_name,
768 variant_iter,
769 )?))
770 } else if let Some(namespace) = namespace {
771 reject_key!(name not on "name-switched enums" only on "their variants");
772 Ok(Self::NameSwitched(NameSwitchedEnum::new(
773 namespace,
774 exhaustive,
775 variant_iter,
776 )?))
777 } else {
778 reject_key!(name not on "dynamic enums" only on "their variants");
779 reject_key!(exhaustive flag not on "dynamic enums" only on "name-switched enums");
780 Ok(Self::Dynamic(DynamicEnum::new(variant_iter)?))
781 }
782 }
783
784 fn make_from_events_statemachine(
786 &self,
787 target_ty_ident: &Ident,
788 state_ty_ident: &Ident,
789 ) -> Result<FromEventsStateMachine> {
790 match self {
791 Self::NameSwitched(ref inner) => {
792 inner.make_from_events_statemachine(target_ty_ident, state_ty_ident)
793 }
794 Self::AttributeSwitched(ref inner) => {
795 inner.make_from_events_statemachine(target_ty_ident, state_ty_ident)
796 }
797 Self::Dynamic(ref inner) => {
798 inner.make_from_events_statemachine(target_ty_ident, state_ty_ident)
799 }
800 }
801 }
802
803 fn make_as_item_iter_statemachine(
805 &self,
806 target_ty_ident: &Ident,
807 state_ty_ident: &Ident,
808 item_iter_ty_lifetime: &Lifetime,
809 ) -> Result<AsItemsStateMachine> {
810 match self {
811 Self::NameSwitched(ref inner) => inner.make_as_item_iter_statemachine(
812 target_ty_ident,
813 state_ty_ident,
814 item_iter_ty_lifetime,
815 ),
816 Self::AttributeSwitched(ref inner) => inner.make_as_item_iter_statemachine(
817 target_ty_ident,
818 state_ty_ident,
819 item_iter_ty_lifetime,
820 ),
821 Self::Dynamic(ref inner) => inner.make_as_item_iter_statemachine(
822 target_ty_ident,
823 state_ty_ident,
824 item_iter_ty_lifetime,
825 ),
826 }
827 }
828}
829
830pub(crate) struct EnumDef {
832 inner: EnumInner,
834
835 target_ty_ident: Ident,
837
838 builder_ty_ident: Ident,
840
841 item_iter_ty_ident: Ident,
843
844 debug: bool,
846
847 deserialize_callback: Option<Path>,
849}
850
851impl EnumDef {
852 pub(crate) fn new<'x, I: IntoIterator<Item = &'x Variant>>(
854 ident: &Ident,
855 mut meta: XmlCompoundMeta,
856 variant_iter: I,
857 ) -> Result<Self> {
858 let builder_ty_ident = match meta.builder.take() {
859 Some(v) => v,
860 None => quote::format_ident!("{}FromXmlBuilder", ident.to_string()),
861 };
862
863 let item_iter_ty_ident = match meta.iterator.take() {
864 Some(v) => v,
865 None => quote::format_ident!("{}AsXmlIterator", ident.to_string()),
866 };
867
868 let debug = meta.debug.take().is_set();
869 let deserialize_callback = meta.deserialize_callback.take();
870
871 Ok(Self {
872 inner: EnumInner::new(meta, variant_iter)?,
873 target_ty_ident: ident.clone(),
874 builder_ty_ident,
875 item_iter_ty_ident,
876 debug,
877 deserialize_callback,
878 })
879 }
880}
881
882impl ItemDef for EnumDef {
883 fn make_from_events_builder(
884 &self,
885 vis: &Visibility,
886 name_ident: &Ident,
887 attrs_ident: &Ident,
888 ) -> Result<FromXmlParts> {
889 let target_ty_ident = &self.target_ty_ident;
890 let builder_ty_ident = &self.builder_ty_ident;
891 let state_ty_ident = quote::format_ident!("{}State", builder_ty_ident);
892
893 let defs = self
894 .inner
895 .make_from_events_statemachine(target_ty_ident, &state_ty_ident)?
896 .render(
897 vis,
898 builder_ty_ident,
899 &state_ty_ident,
900 &TypePath {
901 qself: None,
902 path: target_ty_ident.clone().into(),
903 }
904 .into(),
905 self.deserialize_callback.as_ref(),
906 )?;
907
908 Ok(FromXmlParts {
909 defs,
910 from_events_body: quote! {
911 #builder_ty_ident::new(#name_ident, #attrs_ident, ctx)
912 },
913 builder_ty_ident: builder_ty_ident.clone(),
914 })
915 }
916
917 fn make_as_xml_iter(&self, vis: &Visibility) -> Result<AsXmlParts> {
918 let target_ty_ident = &self.target_ty_ident;
919 let item_iter_ty_ident = &self.item_iter_ty_ident;
920 let item_iter_ty_lifetime = Lifetime {
921 apostrophe: Span::call_site(),
922 ident: Ident::new("xso_proc_as_xml_iter_lifetime", Span::call_site()),
923 };
924 let item_iter_ty = Type::Path(TypePath {
925 qself: None,
926 path: Path {
927 leading_colon: None,
928 segments: [PathSegment {
929 ident: item_iter_ty_ident.clone(),
930 arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
931 colon2_token: None,
932 lt_token: token::Lt {
933 spans: [Span::call_site()],
934 },
935 args: [GenericArgument::Lifetime(item_iter_ty_lifetime.clone())]
936 .into_iter()
937 .collect(),
938 gt_token: token::Gt {
939 spans: [Span::call_site()],
940 },
941 }),
942 }]
943 .into_iter()
944 .collect(),
945 },
946 });
947 let state_ty_ident = quote::format_ident!("{}State", item_iter_ty_ident);
948
949 let defs = self
950 .inner
951 .make_as_item_iter_statemachine(
952 target_ty_ident,
953 &state_ty_ident,
954 &item_iter_ty_lifetime,
955 )?
956 .render(
957 vis,
958 &ref_ty(
959 ty_from_ident(target_ty_ident.clone()).into(),
960 item_iter_ty_lifetime.clone(),
961 ),
962 &state_ty_ident,
963 &item_iter_ty_lifetime,
964 &item_iter_ty,
965 )?;
966
967 Ok(AsXmlParts {
968 defs,
969 as_xml_iter_body: quote! {
970 #item_iter_ty_ident::new(self)
971 },
972 item_iter_ty,
973 item_iter_ty_lifetime,
974 })
975 }
976
977 fn debug(&self) -> bool {
978 self.debug
979 }
980}