1use core::hash::{Hash, Hasher};
13
14use proc_macro2::{Span, TokenStream};
15use quote::{quote, quote_spanned};
16use syn::{meta::ParseNestedMeta, spanned::Spanned, *};
17
18use rxml_validation::NcName;
19
20pub const XMLNS_XML: &str = "http://www.w3.org/XML/1998/namespace";
22pub const XMLNS_XMLNS: &str = "http://www.w3.org/2000/xmlns/";
24
25macro_rules! reject_key {
26 ($key:ident not on $not_allowed_on:literal $(only on $only_allowed_on:literal)?) => {
27 if let Some(ref $key) = $key {
28 return Err(Error::new_spanned(
29 $key,
30 concat!(
31 "`",
32 stringify!($key),
33 "` is not allowed on ",
34 $not_allowed_on,
35 $(
36 " (only on ",
37 $only_allowed_on,
38 ")",
39 )?
40 ),
41 ));
42 }
43 };
44
45 ($key:ident flag not on $not_allowed_on:literal $(only on $only_allowed_on:literal)?) => {
46 if let Flag::Present(ref $key) = $key {
47 return Err(Error::new(
48 *$key,
49 concat!(
50 "`",
51 stringify!($key),
52 "` is not allowed on ",
53 $not_allowed_on,
54 $(
55 " (only on ",
56 $only_allowed_on,
57 ")",
58 )?
59 ),
60 ));
61 }
62 };
63}
64
65pub(crate) use reject_key;
66
67#[derive(Debug, Clone)]
69pub(crate) enum NamespaceRef {
70 LitStr(LitStr),
72
73 Path(Path),
75}
76
77impl NamespaceRef {
78 fn fudge(value: &str, span: Span) -> Self {
79 Self::LitStr(LitStr::new(value, span))
80 }
81}
82
83impl syn::parse::Parse for NamespaceRef {
84 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
85 if input.peek(syn::LitStr) {
86 Ok(Self::LitStr(input.parse()?))
87 } else {
88 Ok(Self::Path(input.parse()?))
89 }
90 }
91}
92
93impl quote::ToTokens for NamespaceRef {
94 fn to_tokens(&self, tokens: &mut TokenStream) {
95 match self {
96 Self::LitStr(ref lit) => lit.to_tokens(tokens),
97 Self::Path(ref path) => path.to_tokens(tokens),
98 }
99 }
100}
101
102#[derive(Debug, Clone)]
104pub(crate) enum NameRef {
105 Literal {
107 value: NcName,
109
110 span: Span,
112 },
113
114 Path(Path),
116}
117
118impl Hash for NameRef {
119 fn hash<H: Hasher>(&self, h: &mut H) {
120 match self {
121 Self::Literal { ref value, .. } => value.hash(h),
122 Self::Path(ref path) => path.hash(h),
123 }
124 }
125}
126
127impl PartialEq for NameRef {
128 fn eq(&self, other: &NameRef) -> bool {
129 match self {
130 Self::Literal {
131 value: ref my_value,
132 ..
133 } => match other {
134 Self::Literal {
135 value: ref other_value,
136 ..
137 } => my_value == other_value,
138 _ => false,
139 },
140 Self::Path(ref my_path) => match other {
141 Self::Path(ref other_path) => my_path == other_path,
142 _ => false,
143 },
144 }
145 }
146}
147
148impl Eq for NameRef {}
149
150impl syn::parse::Parse for NameRef {
151 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
152 if input.peek(syn::LitStr) {
153 let s: LitStr = input.parse()?;
154 let span = s.span();
155 match NcName::try_from(s.value()) {
156 Ok(value) => Ok(Self::Literal { value, span }),
157 Err(e) => Err(Error::new(span, format!("not a valid XML name: {}", e))),
158 }
159 } else {
160 let p: Path = input.parse()?;
161 Ok(Self::Path(p))
162 }
163 }
164}
165
166impl quote::ToTokens for NameRef {
167 fn to_tokens(&self, tokens: &mut TokenStream) {
168 match self {
169 Self::Literal { ref value, span } => {
170 let span = *span;
171 let value = value.as_str();
172 let value = quote_spanned! { span=> #value };
173 tokens.extend(quote! {
179 unsafe { ::xso::exports::rxml::NcNameStr::from_str_unchecked(#value) }
180 })
181 }
182 Self::Path(ref path) => path.to_tokens(tokens),
183 }
184 }
185}
186
187#[derive(Debug)]
193pub(crate) enum AmountConstraint {
194 #[allow(dead_code)]
196 FixedSingle(Span),
197
198 Any(Span),
200}
201
202impl syn::parse::Parse for AmountConstraint {
203 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
204 if input.peek(LitInt) && !input.peek2(token::DotDot) && !input.peek2(token::DotDotEq) {
205 let lit: LitInt = input.parse()?;
206 let value: usize = lit.base10_parse()?;
207 if value == 1 {
208 Ok(Self::FixedSingle(lit.span()))
209 } else {
210 Err(Error::new(lit.span(), "only `1` and `..` are allowed here"))
211 }
212 } else {
213 let p: PatRange = input.parse()?;
214 if let Some(attr) = p.attrs.first() {
215 return Err(Error::new_spanned(attr, "attributes not allowed here"));
216 }
217 if let Some(start) = p.start.as_ref() {
218 return Err(Error::new_spanned(
219 start,
220 "only full ranges (`..`) are allowed here",
221 ));
222 }
223 if let Some(end) = p.end.as_ref() {
224 return Err(Error::new_spanned(
225 end,
226 "only full ranges (`..`) are allowed here",
227 ));
228 }
229 Ok(Self::Any(p.span()))
230 }
231 }
232}
233
234#[derive(Clone, Copy, Debug)]
236pub(crate) enum Flag {
237 Absent,
239
240 Present(
242 #[allow(dead_code)]
247 Span,
248 ),
249}
250
251impl Flag {
252 pub(crate) fn is_set(&self) -> bool {
254 match self {
255 Self::Absent => false,
256 Self::Present(_) => true,
257 }
258 }
259
260 pub(crate) fn take(&mut self) -> Self {
262 let mut result = Flag::Absent;
263 core::mem::swap(&mut result, self);
264 result
265 }
266}
267
268impl<T: Spanned> From<T> for Flag {
269 fn from(other: T) -> Flag {
270 Flag::Present(other.span())
271 }
272}
273
274#[derive(Debug, Default)]
276pub(crate) struct QNameRef {
277 pub(crate) namespace: Option<NamespaceRef>,
279
280 pub(crate) name: Option<NameRef>,
282}
283
284impl QNameRef {
285 fn parse_incremental_from_meta<'x>(
293 &mut self,
294 meta: ParseNestedMeta<'x>,
295 ) -> Result<Option<ParseNestedMeta<'x>>> {
296 if meta.path.is_ident("name") {
297 if self.name.is_some() {
298 return Err(Error::new_spanned(meta.path, "duplicate `name` key"));
299 }
300 let value = meta.value()?;
301 let name_span = value.span();
302 let (new_namespace, new_name) = parse_prefixed_name(value)?;
303 if let Some(new_namespace) = new_namespace {
304 if let Some(namespace) = self.namespace.as_ref() {
305 let mut error = Error::new(
306 name_span,
307 "cannot combine `namespace` key with prefixed `name`",
308 );
309 error.combine(Error::new_spanned(namespace, "`namespace` was set here"));
310 return Err(error);
311 }
312 self.namespace = Some(new_namespace);
313 }
314 self.name = Some(new_name);
315 Ok(None)
316 } else if meta.path.is_ident("namespace") {
317 if self.namespace.is_some() {
318 return Err(Error::new_spanned(
319 meta.path,
320 "duplicate `namespace` key or `name` key has prefix",
321 ));
322 }
323 self.namespace = Some(meta.value()?.parse()?);
324 Ok(None)
325 } else {
326 Ok(Some(meta))
327 }
328 }
329}
330
331#[derive(Debug)]
333pub(crate) struct XmlCompoundMeta {
334 pub(crate) span: Span,
338
339 pub(crate) qname: QNameRef,
342
343 pub(crate) debug: Flag,
345
346 pub(crate) builder: Option<Ident>,
348
349 pub(crate) iterator: Option<Ident>,
351
352 pub(crate) on_unknown_attribute: Option<Ident>,
355
356 pub(crate) on_unknown_child: Option<Ident>,
359
360 pub(crate) exhaustive: Flag,
362
363 pub(crate) transparent: Flag,
365}
366
367impl XmlCompoundMeta {
368 fn parse_from_attribute(attr: &Attribute) -> Result<Self> {
373 let mut qname = QNameRef::default();
374 let mut builder = None;
375 let mut iterator = None;
376 let mut on_unknown_attribute = None;
377 let mut on_unknown_child = None;
378 let mut debug = Flag::Absent;
379 let mut exhaustive = Flag::Absent;
380 let mut transparent = Flag::Absent;
381
382 attr.parse_nested_meta(|meta| {
383 if meta.path.is_ident("debug") {
384 if debug.is_set() {
385 return Err(Error::new_spanned(meta.path, "duplicate `debug` key"));
386 }
387 debug = (&meta.path).into();
388 Ok(())
389 } else if meta.path.is_ident("builder") {
390 if builder.is_some() {
391 return Err(Error::new_spanned(meta.path, "duplicate `builder` key"));
392 }
393 builder = Some(meta.value()?.parse()?);
394 Ok(())
395 } else if meta.path.is_ident("iterator") {
396 if iterator.is_some() {
397 return Err(Error::new_spanned(meta.path, "duplicate `iterator` key"));
398 }
399 iterator = Some(meta.value()?.parse()?);
400 Ok(())
401 } else if meta.path.is_ident("on_unknown_attribute") {
402 if on_unknown_attribute.is_some() {
403 return Err(Error::new_spanned(
404 meta.path,
405 "duplicate `on_unknown_attribute` key",
406 ));
407 }
408 on_unknown_attribute = Some(meta.value()?.parse()?);
409 Ok(())
410 } else if meta.path.is_ident("on_unknown_child") {
411 if on_unknown_child.is_some() {
412 return Err(Error::new_spanned(
413 meta.path,
414 "duplicate `on_unknown_child` key",
415 ));
416 }
417 on_unknown_child = Some(meta.value()?.parse()?);
418 Ok(())
419 } else if meta.path.is_ident("exhaustive") {
420 if exhaustive.is_set() {
421 return Err(Error::new_spanned(meta.path, "duplicate `exhaustive` key"));
422 }
423 exhaustive = (&meta.path).into();
424 Ok(())
425 } else if meta.path.is_ident("transparent") {
426 if transparent.is_set() {
427 return Err(Error::new_spanned(meta.path, "duplicate `transparent` key"));
428 }
429 transparent = (&meta.path).into();
430 Ok(())
431 } else {
432 match qname.parse_incremental_from_meta(meta)? {
433 None => Ok(()),
434 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
435 }
436 }
437 })?;
438
439 Ok(Self {
440 span: attr.span(),
441 qname,
442 debug,
443 builder,
444 iterator,
445 on_unknown_attribute,
446 on_unknown_child,
447 exhaustive,
448 transparent,
449 })
450 }
451
452 pub(crate) fn try_parse_from_attributes(attrs: &[Attribute]) -> Result<Option<Self>> {
463 let mut result = None;
464 for attr in attrs {
465 if !attr.path().is_ident("xml") {
466 continue;
467 }
468 if result.is_some() {
469 return Err(syn::Error::new_spanned(
470 attr.path(),
471 "only one #[xml(..)] per struct or enum variant allowed",
472 ));
473 }
474 result = Some(Self::parse_from_attribute(attr)?);
475 }
476 Ok(result)
477 }
478
479 pub(crate) fn parse_from_attributes(attrs: &[Attribute]) -> Result<Self> {
488 match Self::try_parse_from_attributes(attrs)? {
489 Some(v) => Ok(v),
490 None => Err(syn::Error::new(
491 Span::call_site(),
492 "#[xml(..)] attribute required on struct or enum variant",
493 )),
494 }
495 }
496}
497
498fn maybe_type_path(p: parse::ParseStream<'_>) -> (bool, Option<Span>) {
507 let cursor = if p.peek(token::PathSep) {
511 p.cursor().punct().unwrap().1.punct().unwrap().1
516 } else {
517 p.cursor()
519 };
520
521 let mut cursor = cursor;
525 loop {
526 let Some((_, new_cursor)) = cursor.ident() else {
529 return (false, None);
530 };
531 cursor = new_cursor;
532
533 let Some((punct, new_cursor)) = cursor.punct() else {
536 return (false, None);
537 };
538 cursor = new_cursor;
539
540 match punct.as_char() {
541 '<' => return (true, Some(punct.span())),
544
545 ':' => (),
547
548 _ => return (false, None),
552 }
553
554 let Some((punct, new_cursor)) = cursor.punct() else {
556 return (false, None);
557 };
558 cursor = new_cursor;
559
560 if punct.as_char() != ':' {
561 return (false, None);
563 }
564
565 }
571}
572
573fn parse_codec_expr(p: parse::ParseStream<'_>) -> Result<(Expr, Option<Error>)> {
588 let (maybe_type_path, punct_span) = maybe_type_path(p);
589 if maybe_type_path {
590 let helpful_error =
591 punct_span.map(|span| Error::new(span, "help: try inserting a `::` before this `<`"));
592 let mut type_path: TypePath = match p.parse() {
593 Ok(v) => v,
594 Err(mut e) => match helpful_error {
595 Some(help) => {
596 e.combine(help);
597 return Err(e);
598 }
599 None => return Err(e),
600 },
601 };
602 for segment in type_path.path.segments.iter_mut() {
605 match segment.arguments {
606 PathArguments::AngleBracketed(ref mut arguments) => {
607 let span = arguments.span();
608 arguments
609 .colon2_token
610 .get_or_insert_with(|| token::PathSep {
611 spans: [span, span],
612 });
613 }
614 _ => (),
615 }
616 }
617 Ok((
618 Expr::Path(ExprPath {
619 attrs: Vec::new(),
620 qself: type_path.qself,
621 path: type_path.path,
622 }),
623 helpful_error,
624 ))
625 } else {
626 p.parse().map(|x| (x, None))
627 }
628}
629
630fn parse_prefixed_name(
632 value: syn::parse::ParseStream<'_>,
633) -> Result<(Option<NamespaceRef>, NameRef)> {
634 if !value.peek(LitStr) {
635 return Ok((None, value.parse()?));
638 }
639
640 let name: LitStr = value.parse()?;
641 let name_span = name.span();
642 let (prefix, name) = match name
643 .value()
644 .try_into()
645 .and_then(|name: rxml_validation::Name| name.split_name())
646 {
647 Ok(v) => v,
648 Err(e) => {
649 return Err(Error::new(
650 name_span,
651 format!("not a valid XML name: {}", e),
652 ))
653 }
654 };
655 let name = NameRef::Literal {
656 value: name,
657 span: name_span,
658 };
659 if let Some(prefix) = prefix {
660 let namespace_uri = match prefix.as_str() {
661 "xml" => XMLNS_XML,
662 "xmlns" => XMLNS_XMLNS,
663 other => return Err(Error::new(
664 name_span,
665 format!("prefix `{}` is not a built-in prefix and cannot be used. specify the desired namespace using the `namespace` key instead.", other)
666 )),
667 };
668 Ok((Some(NamespaceRef::fudge(namespace_uri, name_span)), name))
669 } else {
670 Ok((None, name))
671 }
672}
673
674#[derive(Debug)]
676pub(crate) enum XmlFieldMeta {
677 Attribute {
679 span: Span,
683
684 qname: QNameRef,
686
687 default_: Flag,
689
690 type_: Option<Type>,
692
693 codec: Option<Expr>,
695 },
696
697 Text {
699 span: Span,
703
704 codec: Option<Expr>,
706
707 type_: Option<Type>,
709 },
710
711 Child {
713 span: Span,
717
718 default_: Flag,
720
721 amount: Option<AmountConstraint>,
723 },
724
725 Extract {
727 span: Span,
731
732 qname: QNameRef,
734
735 amount: Option<AmountConstraint>,
737
738 default_: Flag,
740
741 fields: Vec<XmlFieldMeta>,
743
744 on_unknown_attribute: Option<Ident>,
746
747 on_unknown_child: Option<Ident>,
749 },
750
751 Element {
753 span: Span,
757
758 default_: Flag,
760
761 amount: Option<AmountConstraint>,
763 },
764
765 Flag {
767 span: Span,
771
772 qname: QNameRef,
774 },
775}
776
777impl XmlFieldMeta {
778 fn attribute_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
785 if meta.input.peek(Token![=]) {
786 let (namespace, name) = parse_prefixed_name(meta.value()?)?;
788 Ok(Self::Attribute {
789 span: meta.path.span(),
790 qname: QNameRef {
791 name: Some(name),
792 namespace,
793 },
794 default_: Flag::Absent,
795 type_: None,
796 codec: None,
797 })
798 } else if meta.input.peek(syn::token::Paren) {
799 let mut qname = QNameRef::default();
801 let mut default_ = Flag::Absent;
802 let mut type_ = None;
803 let mut codec = None;
804 meta.parse_nested_meta(|meta| {
805 if meta.path.is_ident("default") {
806 if default_.is_set() {
807 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
808 }
809 default_ = (&meta.path).into();
810 Ok(())
811 } else if meta.path.is_ident("type_") {
812 if type_.is_some() {
813 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
814 }
815 type_ = Some(meta.value()?.parse()?);
816 Ok(())
817 } else if meta.path.is_ident("codec") {
818 if codec.is_some() {
819 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
820 }
821 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
822 let lookahead = meta.input.lookahead1();
825 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
826 if let Some(helpful_error) = helpful_error {
827 let mut e = lookahead.error();
828 e.combine(helpful_error);
829 return Err(e);
830 }
831 }
832 codec = Some(new_codec);
833 Ok(())
834 } else {
835 match qname.parse_incremental_from_meta(meta)? {
836 None => Ok(()),
837 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
838 }
839 }
840 })?;
841 Ok(Self::Attribute {
842 span: meta.path.span(),
843 qname,
844 default_,
845 type_,
846 codec,
847 })
848 } else {
849 Ok(Self::Attribute {
851 span: meta.path.span(),
852 qname: QNameRef::default(),
853 default_: Flag::Absent,
854 type_: None,
855 codec: None,
856 })
857 }
858 }
859
860 fn text_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
862 if meta.input.peek(Token![=]) {
863 let (codec, helpful_error) = parse_codec_expr(meta.value()?)?;
864 let lookahead = meta.input.lookahead1();
874 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
875 if let Some(helpful_error) = helpful_error {
876 let mut e = lookahead.error();
877 e.combine(helpful_error);
878 return Err(e);
879 }
880 }
881 Ok(Self::Text {
882 span: meta.path.span(),
883 type_: None,
884 codec: Some(codec),
885 })
886 } else if meta.input.peek(syn::token::Paren) {
887 let mut codec: Option<Expr> = None;
888 let mut type_: Option<Type> = None;
889 meta.parse_nested_meta(|meta| {
890 if meta.path.is_ident("codec") {
891 if codec.is_some() {
892 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
893 }
894 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
895 let lookahead = meta.input.lookahead1();
898 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
899 if let Some(helpful_error) = helpful_error {
900 let mut e = lookahead.error();
901 e.combine(helpful_error);
902 return Err(e);
903 }
904 }
905 codec = Some(new_codec);
906 Ok(())
907 } else if meta.path.is_ident("type_") {
908 if type_.is_some() {
909 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
910 }
911 type_ = Some(meta.value()?.parse()?);
912 Ok(())
913 } else {
914 Err(Error::new_spanned(meta.path, "unsupported key"))
915 }
916 })?;
917 Ok(Self::Text {
918 span: meta.path.span(),
919 type_,
920 codec,
921 })
922 } else {
923 Ok(Self::Text {
924 span: meta.path.span(),
925 type_: None,
926 codec: None,
927 })
928 }
929 }
930
931 fn child_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
933 if meta.input.peek(syn::token::Paren) {
934 let mut default_ = Flag::Absent;
935 let mut amount = None;
936 meta.parse_nested_meta(|meta| {
937 if meta.path.is_ident("default") {
938 if default_.is_set() {
939 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
940 }
941 default_ = (&meta.path).into();
942 Ok(())
943 } else if meta.path.is_ident("n") {
944 if amount.is_some() {
945 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
946 }
947 amount = Some(meta.value()?.parse()?);
948 Ok(())
949 } else {
950 Err(Error::new_spanned(meta.path, "unsupported key"))
951 }
952 })?;
953 Ok(Self::Child {
954 span: meta.path.span(),
955 default_,
956 amount,
957 })
958 } else {
959 Ok(Self::Child {
960 span: meta.path.span(),
961 default_: Flag::Absent,
962 amount: None,
963 })
964 }
965 }
966
967 fn extract_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
969 let mut qname = QNameRef::default();
970 let mut fields = None;
971 let mut amount = None;
972 let mut on_unknown_attribute = None;
973 let mut on_unknown_child = None;
974 let mut default_ = Flag::Absent;
975 meta.parse_nested_meta(|meta| {
976 if meta.path.is_ident("default") {
977 if default_.is_set() {
978 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
979 }
980 default_ = (&meta.path).into();
981 Ok(())
982 } else if meta.path.is_ident("fields") {
983 if let Some((fields_span, _)) = fields.as_ref() {
984 let mut error = Error::new_spanned(meta.path, "duplicate `fields` meta");
985 error.combine(Error::new(*fields_span, "previous `fields` meta was here"));
986 return Err(error);
987 }
988 let mut new_fields = Vec::new();
989 meta.parse_nested_meta(|meta| {
990 new_fields.push(XmlFieldMeta::parse_from_meta(meta)?);
991 Ok(())
992 })?;
993 fields = Some((meta.path.span(), new_fields));
994 Ok(())
995 } else if meta.path.is_ident("n") {
996 if amount.is_some() {
997 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
998 }
999 amount = Some(meta.value()?.parse()?);
1000 Ok(())
1001 } else if meta.path.is_ident("on_unknown_attribute") {
1002 if on_unknown_attribute.is_some() {
1003 return Err(Error::new_spanned(
1004 meta.path,
1005 "duplicate `on_unknown_attribute` key",
1006 ));
1007 }
1008 on_unknown_attribute = Some(meta.value()?.parse()?);
1009 Ok(())
1010 } else if meta.path.is_ident("on_unknown_child") {
1011 if on_unknown_child.is_some() {
1012 return Err(Error::new_spanned(
1013 meta.path,
1014 "duplicate `on_unknown_child` key",
1015 ));
1016 }
1017 on_unknown_child = Some(meta.value()?.parse()?);
1018 Ok(())
1019 } else {
1020 match qname.parse_incremental_from_meta(meta)? {
1021 None => Ok(()),
1022 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1023 }
1024 }
1025 })?;
1026 let fields = fields.map(|(_, x)| x).unwrap_or_else(Vec::new);
1027 Ok(Self::Extract {
1028 span: meta.path.span(),
1029 default_,
1030 qname,
1031 fields,
1032 amount,
1033 on_unknown_attribute,
1034 on_unknown_child,
1035 })
1036 }
1037
1038 fn element_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1040 let mut amount = None;
1041 let mut default_ = Flag::Absent;
1042 if meta.input.peek(syn::token::Paren) {
1043 meta.parse_nested_meta(|meta| {
1044 if meta.path.is_ident("default") {
1045 if default_.is_set() {
1046 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1047 }
1048 default_ = (&meta.path).into();
1049 Ok(())
1050 } else if meta.path.is_ident("n") {
1051 if amount.is_some() {
1052 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1053 }
1054 amount = Some(meta.value()?.parse()?);
1055 Ok(())
1056 } else {
1057 Err(Error::new_spanned(meta.path, "unsupported key"))
1058 }
1059 })?;
1060 }
1061 Ok(Self::Element {
1062 span: meta.path.span(),
1063 default_,
1064 amount,
1065 })
1066 }
1067
1068 fn flag_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1070 let mut qname = QNameRef::default();
1071 if meta.input.peek(syn::token::Paren) {
1072 meta.parse_nested_meta(|meta| match qname.parse_incremental_from_meta(meta)? {
1073 None => Ok(()),
1074 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1075 })?;
1076 }
1077 Ok(Self::Flag {
1078 span: meta.path.span(),
1079 qname,
1080 })
1081 }
1082
1083 fn parse_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1086 if meta.path.is_ident("attribute") {
1087 Self::attribute_from_meta(meta)
1088 } else if meta.path.is_ident("text") {
1089 Self::text_from_meta(meta)
1090 } else if meta.path.is_ident("child") {
1091 Self::child_from_meta(meta)
1092 } else if meta.path.is_ident("extract") {
1093 Self::extract_from_meta(meta)
1094 } else if meta.path.is_ident("element") {
1095 Self::element_from_meta(meta)
1096 } else if meta.path.is_ident("flag") {
1097 Self::flag_from_meta(meta)
1098 } else {
1099 Err(Error::new_spanned(meta.path, "unsupported field meta"))
1100 }
1101 }
1102
1103 pub(crate) fn parse_from_attribute(attr: &Attribute) -> Result<Self> {
1116 let mut result: Option<Self> = None;
1117
1118 attr.parse_nested_meta(|meta| {
1119 if result.is_some() {
1120 return Err(Error::new_spanned(
1121 meta.path,
1122 "multiple field type specifiers are not supported",
1123 ));
1124 }
1125
1126 result = Some(Self::parse_from_meta(meta)?);
1127 Ok(())
1128 })?;
1129
1130 if let Some(result) = result {
1131 Ok(result)
1132 } else {
1133 Err(Error::new_spanned(
1134 attr,
1135 "missing field type specifier within `#[xml(..)]`",
1136 ))
1137 }
1138 }
1139
1140 pub(crate) fn parse_from_attributes(attrs: &[Attribute], err_span: &Span) -> Result<Self> {
1148 let mut result: Option<Self> = None;
1149 for attr in attrs {
1150 if !attr.path().is_ident("xml") {
1151 continue;
1152 }
1153
1154 if result.is_some() {
1155 return Err(Error::new_spanned(
1156 attr,
1157 "only one #[xml(..)] attribute per field allowed.",
1158 ));
1159 }
1160
1161 result = Some(Self::parse_from_attribute(attr)?);
1162 }
1163
1164 if let Some(result) = result {
1165 Ok(result)
1166 } else {
1167 Err(Error::new(*err_span, "missing #[xml(..)] meta on field"))
1168 }
1169 }
1170
1171 pub(crate) fn span(&self) -> Span {
1174 match self {
1175 Self::Attribute { ref span, .. } => *span,
1176 Self::Child { ref span, .. } => *span,
1177 Self::Text { ref span, .. } => *span,
1178 Self::Extract { ref span, .. } => *span,
1179 Self::Element { ref span, .. } => *span,
1180 Self::Flag { ref span, .. } => *span,
1181 }
1182 }
1183
1184 pub(crate) fn take_type(&mut self) -> Option<Type> {
1186 match self {
1187 Self::Attribute { ref mut type_, .. } => type_.take(),
1188 Self::Text { ref mut type_, .. } => type_.take(),
1189 _ => None,
1190 }
1191 }
1192}