1use proc_macro2::{Span, TokenStream};
12use quote::quote;
13use syn::*;
14
15use crate::common::GenericsInfo;
16use crate::error_message::{FieldName, ParentRef};
17use crate::meta::{NameRef, NamespaceRef};
18use crate::scope::{AsItemsScope, FromEventsScope};
19use crate::types::{bool_ty, empty_builder_ty, u8_ty};
20
21use super::{Field, FieldBuilderPart, FieldIteratorPart, FieldTempInit, NestedMatcher};
22
23pub(super) struct FlagField {
25 pub(super) xml_namespace: NamespaceRef,
27
28 pub(super) xml_name: NameRef,
30}
31
32impl Field for FlagField {
33 fn make_builder_part(
34 &self,
35 scope: &FromEventsScope,
36 _generics: &mut GenericsInfo,
37 container_name: &ParentRef,
38 member: &Member,
39 _ty: &Type,
40 ) -> Result<FieldBuilderPart> {
41 let field_access = scope.access_field(member);
42
43 let unknown_attr_err = format!(
44 "Unknown attribute in flag child {} in {}.",
45 FieldName(member),
46 container_name
47 );
48 let unknown_child_err = format!(
49 "Unknown child in flag child {} in {}.",
50 FieldName(member),
51 container_name
52 );
53 let unknown_text_err = format!(
54 "Unexpected text in flag child {} in {}.",
55 FieldName(member),
56 container_name
57 );
58
59 let xml_namespace = &self.xml_namespace;
60 let xml_name = &self.xml_name;
61
62 Ok(FieldBuilderPart::Nested {
63 extra_defs: TokenStream::new(),
64 value: FieldTempInit {
65 ty: bool_ty(Span::call_site()),
66 init: quote! { false },
67 },
68 matcher: NestedMatcher::Selective(quote! {
69 if name.0 == #xml_namespace && name.1 == #xml_name {
70 ::xso::fromxml::Empty {
71 attributeerr: #unknown_attr_err,
72 childerr: #unknown_child_err,
73 texterr: #unknown_text_err,
74 }.start(attrs).map_err(
75 ::xso::error::FromEventsError::Invalid
76 )
77 } else {
78 ::core::result::Result::Err(::xso::error::FromEventsError::Mismatch {
79 name,
80 attrs,
81 })
82 }
83 }),
84 builder: empty_builder_ty(Span::call_site()),
85 collect: quote! {
86 #field_access = true;
87 },
88 finalize: quote! {
89 #field_access
90 },
91 })
92 }
93
94 fn make_iterator_part(
95 &self,
96 _scope: &AsItemsScope,
97 _generics: &mut GenericsInfo,
98 _container_name: &ParentRef,
99 bound_name: &Ident,
100 _member: &Member,
101 _ty: &Type,
102 ) -> Result<FieldIteratorPart> {
103 let xml_namespace = &self.xml_namespace;
104 let xml_name = &self.xml_name;
105
106 Ok(FieldIteratorPart::Content {
107 extra_defs: TokenStream::new(),
108 value: FieldTempInit {
109 init: quote! {
110 if *#bound_name {
111 3
112 } else {
113 1
114 }
115 },
116 ty: u8_ty(Span::call_site()),
117 },
118 generator: quote! {
119 {
120 #bound_name = #bound_name.wrapping_sub(1);
123 match #bound_name {
124 0 => ::core::result::Result::<_, ::xso::error::Error>::Ok(::core::option::Option::None),
125 1 => ::core::result::Result::Ok(::core::option::Option::Some(
126 ::xso::Item::ElementFoot
127 )),
128 2 => ::core::result::Result::Ok(::core::option::Option::Some(
129 ::xso::Item::ElementHeadStart(
130 ::xso::exports::rxml::Namespace::from(#xml_namespace),
131 ::xso::exports::alloc::borrow::Cow::Borrowed(#xml_name),
132 )
133 )),
134 _ => unreachable!(),
135 }
136 }
137 },
138 })
139 }
140}