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 ($key:ident vec not on $not_allowed_on:literal $(only on $only_allowed_on:literal)?) => {
65 if let Some(ref $key) = $key.first() {
66 return Err(Error::new(
67 $key.span(),
68 concat!(
69 "`",
70 stringify!($key),
71 "` is not allowed on ",
72 $not_allowed_on,
73 $(
74 " (only on ",
75 $only_allowed_on,
76 ")",
77 )?
78 ),
79 ));
80 }
81 };
82}
83
84pub(crate) use reject_key;
85
86#[derive(Debug, Clone)]
88pub(crate) enum NamespaceRef {
89 LitStr(LitStr),
91
92 Path(Path),
94}
95
96impl NamespaceRef {
97 fn fudge(value: &str, span: Span) -> Self {
98 Self::LitStr(LitStr::new(value, span))
99 }
100}
101
102impl syn::parse::Parse for NamespaceRef {
103 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
104 if input.peek(syn::LitStr) {
105 Ok(Self::LitStr(input.parse()?))
106 } else {
107 Ok(Self::Path(input.parse()?))
108 }
109 }
110}
111
112impl quote::ToTokens for NamespaceRef {
113 fn to_tokens(&self, tokens: &mut TokenStream) {
114 match self {
115 Self::LitStr(ref lit) => lit.to_tokens(tokens),
116 Self::Path(ref path) => path.to_tokens(tokens),
117 }
118 }
119}
120
121#[derive(Debug, Clone)]
123pub(crate) enum NameRef {
124 Literal {
126 value: NcName,
128
129 span: Span,
131 },
132
133 Path(Path),
135}
136
137impl Hash for NameRef {
138 fn hash<H: Hasher>(&self, h: &mut H) {
139 match self {
140 Self::Literal { ref value, .. } => value.hash(h),
141 Self::Path(ref path) => path.hash(h),
142 }
143 }
144}
145
146impl PartialEq for NameRef {
147 fn eq(&self, other: &NameRef) -> bool {
148 match self {
149 Self::Literal {
150 value: ref my_value,
151 ..
152 } => match other {
153 Self::Literal {
154 value: ref other_value,
155 ..
156 } => my_value == other_value,
157 _ => false,
158 },
159 Self::Path(ref my_path) => match other {
160 Self::Path(ref other_path) => my_path == other_path,
161 _ => false,
162 },
163 }
164 }
165}
166
167impl Eq for NameRef {}
168
169impl syn::parse::Parse for NameRef {
170 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
171 if input.peek(syn::LitStr) {
172 let s: LitStr = input.parse()?;
173 let span = s.span();
174 match NcName::try_from(s.value()) {
175 Ok(value) => Ok(Self::Literal { value, span }),
176 Err(e) => Err(Error::new(span, format!("not a valid XML name: {}", e))),
177 }
178 } else {
179 let p: Path = input.parse()?;
180 Ok(Self::Path(p))
181 }
182 }
183}
184
185impl quote::ToTokens for NameRef {
186 fn to_tokens(&self, tokens: &mut TokenStream) {
187 match self {
188 Self::Literal { ref value, span } => {
189 let span = *span;
190 let value = value.as_str();
191 let value = quote_spanned! { span=> #value };
192 tokens.extend(quote! {
198 unsafe { ::xso::exports::rxml::NcNameStr::from_str_unchecked(#value) }
199 })
200 }
201 Self::Path(ref path) => path.to_tokens(tokens),
202 }
203 }
204}
205
206#[derive(Debug)]
212pub(crate) enum AmountConstraint {
213 #[allow(dead_code)]
215 FixedSingle(Span),
216
217 Any(Span),
219}
220
221impl syn::parse::Parse for AmountConstraint {
222 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
223 if input.peek(LitInt) && !input.peek2(token::DotDot) && !input.peek2(token::DotDotEq) {
224 let lit: LitInt = input.parse()?;
225 let value: usize = lit.base10_parse()?;
226 if value == 1 {
227 Ok(Self::FixedSingle(lit.span()))
228 } else {
229 Err(Error::new(lit.span(), "only `1` and `..` are allowed here"))
230 }
231 } else {
232 let p: PatRange = input.parse()?;
233 if let Some(attr) = p.attrs.first() {
234 return Err(Error::new_spanned(attr, "attributes not allowed here"));
235 }
236 if let Some(start) = p.start.as_ref() {
237 return Err(Error::new_spanned(
238 start,
239 "only full ranges (`..`) are allowed here",
240 ));
241 }
242 if let Some(end) = p.end.as_ref() {
243 return Err(Error::new_spanned(
244 end,
245 "only full ranges (`..`) are allowed here",
246 ));
247 }
248 Ok(Self::Any(p.span()))
249 }
250 }
251}
252
253#[derive(Clone, Copy, Debug)]
255pub(crate) enum Flag {
256 Absent,
258
259 Present(
261 #[allow(dead_code)]
266 Span,
267 ),
268}
269
270impl Flag {
271 pub(crate) fn is_set(&self) -> bool {
273 match self {
274 Self::Absent => false,
275 Self::Present(_) => true,
276 }
277 }
278
279 pub(crate) fn take(&mut self) -> Self {
281 let mut result = Flag::Absent;
282 core::mem::swap(&mut result, self);
283 result
284 }
285}
286
287impl<T: Spanned> From<T> for Flag {
288 fn from(other: T) -> Flag {
289 Flag::Present(other.span())
290 }
291}
292
293#[derive(Debug, Default)]
295pub(crate) struct QNameRef {
296 pub(crate) namespace: Option<NamespaceRef>,
298
299 pub(crate) name: Option<NameRef>,
301}
302
303impl QNameRef {
304 fn parse_incremental_from_meta<'x>(
312 &mut self,
313 meta: ParseNestedMeta<'x>,
314 ) -> Result<Option<ParseNestedMeta<'x>>> {
315 if meta.path.is_ident("name") {
316 if self.name.is_some() {
317 return Err(Error::new_spanned(meta.path, "duplicate `name` key"));
318 }
319 let value = meta.value()?;
320 let name_span = value.span();
321 let (new_namespace, new_name) = parse_prefixed_name(value)?;
322 if let Some(new_namespace) = new_namespace {
323 if let Some(namespace) = self.namespace.as_ref() {
324 let mut error = Error::new(
325 name_span,
326 "cannot combine `namespace` key with prefixed `name`",
327 );
328 error.combine(Error::new_spanned(namespace, "`namespace` was set here"));
329 return Err(error);
330 }
331 self.namespace = Some(new_namespace);
332 }
333 self.name = Some(new_name);
334 Ok(None)
335 } else if meta.path.is_ident("namespace") {
336 if self.namespace.is_some() {
337 return Err(Error::new_spanned(
338 meta.path,
339 "duplicate `namespace` key or `name` key has prefix",
340 ));
341 }
342 self.namespace = Some(meta.value()?.parse()?);
343 Ok(None)
344 } else {
345 Ok(Some(meta))
346 }
347 }
348}
349
350#[derive(Debug)]
352pub(crate) enum DiscardSpec {
353 Attribute {
355 span: Span,
359
360 qname: QNameRef,
363 },
364
365 Text {
367 span: Span,
371 },
372}
373
374impl DiscardSpec {
375 pub(crate) fn span(&self) -> Span {
376 match self {
377 Self::Attribute { ref span, .. } => *span,
378 Self::Text { ref span, .. } => *span,
379 }
380 }
381}
382
383impl TryFrom<XmlFieldMeta> for DiscardSpec {
384 type Error = syn::Error;
385
386 fn try_from(other: XmlFieldMeta) -> Result<Self> {
387 match other {
388 XmlFieldMeta::Attribute {
389 span,
390 qname,
391 default_,
392 type_,
393 codec,
394 } => {
395 reject_key!(default_ flag not on "discard specifications" only on "fields");
396 reject_key!(type_ not on "discard specifications" only on "fields");
397 reject_key!(codec not on "discard specifications" only on "fields");
398 Ok(Self::Attribute { span, qname })
399 }
400 XmlFieldMeta::Text { span, type_, codec } => {
401 reject_key!(type_ not on "discard specifications" only on "fields");
402 reject_key!(codec not on "discard specifications" only on "fields");
403 Ok(Self::Text { span })
404 }
405 other => Err(Error::new(
406 other.span(),
407 "cannot discard this kind of child",
408 )),
409 }
410 }
411}
412
413#[derive(Debug)]
415pub(crate) struct XmlCompoundMeta {
416 pub(crate) span: Span,
420
421 pub(crate) qname: QNameRef,
424
425 pub(crate) debug: Flag,
427
428 pub(crate) builder: Option<Ident>,
430
431 pub(crate) iterator: Option<Ident>,
433
434 pub(crate) on_unknown_attribute: Option<Ident>,
437
438 pub(crate) on_unknown_child: Option<Ident>,
441
442 pub(crate) exhaustive: Flag,
444
445 pub(crate) transparent: Flag,
447
448 pub(crate) discard: Vec<DiscardSpec>,
450}
451
452impl XmlCompoundMeta {
453 fn parse_from_attribute(attr: &Attribute) -> Result<Self> {
458 let mut qname = QNameRef::default();
459 let mut builder = None;
460 let mut iterator = None;
461 let mut on_unknown_attribute = None;
462 let mut on_unknown_child = None;
463 let mut debug = Flag::Absent;
464 let mut exhaustive = Flag::Absent;
465 let mut transparent = Flag::Absent;
466 let mut discard = Vec::new();
467
468 attr.parse_nested_meta(|meta| {
469 if meta.path.is_ident("debug") {
470 if debug.is_set() {
471 return Err(Error::new_spanned(meta.path, "duplicate `debug` key"));
472 }
473 debug = (&meta.path).into();
474 Ok(())
475 } else if meta.path.is_ident("builder") {
476 if builder.is_some() {
477 return Err(Error::new_spanned(meta.path, "duplicate `builder` key"));
478 }
479 builder = Some(meta.value()?.parse()?);
480 Ok(())
481 } else if meta.path.is_ident("iterator") {
482 if iterator.is_some() {
483 return Err(Error::new_spanned(meta.path, "duplicate `iterator` key"));
484 }
485 iterator = Some(meta.value()?.parse()?);
486 Ok(())
487 } else if meta.path.is_ident("on_unknown_attribute") {
488 if on_unknown_attribute.is_some() {
489 return Err(Error::new_spanned(
490 meta.path,
491 "duplicate `on_unknown_attribute` key",
492 ));
493 }
494 on_unknown_attribute = Some(meta.value()?.parse()?);
495 Ok(())
496 } else if meta.path.is_ident("on_unknown_child") {
497 if on_unknown_child.is_some() {
498 return Err(Error::new_spanned(
499 meta.path,
500 "duplicate `on_unknown_child` key",
501 ));
502 }
503 on_unknown_child = Some(meta.value()?.parse()?);
504 Ok(())
505 } else if meta.path.is_ident("exhaustive") {
506 if exhaustive.is_set() {
507 return Err(Error::new_spanned(meta.path, "duplicate `exhaustive` key"));
508 }
509 exhaustive = (&meta.path).into();
510 Ok(())
511 } else if meta.path.is_ident("transparent") {
512 if transparent.is_set() {
513 return Err(Error::new_spanned(meta.path, "duplicate `transparent` key"));
514 }
515 transparent = (&meta.path).into();
516 Ok(())
517 } else if meta.path.is_ident("discard") {
518 meta.parse_nested_meta(|meta| {
519 discard.push(XmlFieldMeta::parse_from_meta(meta)?.try_into()?);
520 Ok(())
521 })?;
522 Ok(())
523 } else {
524 match qname.parse_incremental_from_meta(meta)? {
525 None => Ok(()),
526 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
527 }
528 }
529 })?;
530
531 Ok(Self {
532 span: attr.span(),
533 qname,
534 debug,
535 builder,
536 iterator,
537 on_unknown_attribute,
538 on_unknown_child,
539 exhaustive,
540 transparent,
541 discard,
542 })
543 }
544
545 pub(crate) fn try_parse_from_attributes(attrs: &[Attribute]) -> Result<Option<Self>> {
556 let mut result = None;
557 for attr in attrs {
558 if !attr.path().is_ident("xml") {
559 continue;
560 }
561 if result.is_some() {
562 return Err(syn::Error::new_spanned(
563 attr.path(),
564 "only one #[xml(..)] per struct or enum variant allowed",
565 ));
566 }
567 result = Some(Self::parse_from_attribute(attr)?);
568 }
569 Ok(result)
570 }
571
572 pub(crate) fn parse_from_attributes(attrs: &[Attribute]) -> Result<Self> {
581 match Self::try_parse_from_attributes(attrs)? {
582 Some(v) => Ok(v),
583 None => Err(syn::Error::new(
584 Span::call_site(),
585 "#[xml(..)] attribute required on struct or enum variant",
586 )),
587 }
588 }
589}
590
591fn maybe_type_path(p: parse::ParseStream<'_>) -> (bool, Option<Span>) {
600 let cursor = if p.peek(token::PathSep) {
604 p.cursor().punct().unwrap().1.punct().unwrap().1
609 } else {
610 p.cursor()
612 };
613
614 let mut cursor = cursor;
618 loop {
619 let Some((_, new_cursor)) = cursor.ident() else {
622 return (false, None);
623 };
624 cursor = new_cursor;
625
626 let Some((punct, new_cursor)) = cursor.punct() else {
629 return (false, None);
630 };
631 cursor = new_cursor;
632
633 match punct.as_char() {
634 '<' => return (true, Some(punct.span())),
637
638 ':' => (),
640
641 _ => return (false, None),
645 }
646
647 let Some((punct, new_cursor)) = cursor.punct() else {
649 return (false, None);
650 };
651 cursor = new_cursor;
652
653 if punct.as_char() != ':' {
654 return (false, None);
656 }
657
658 }
664}
665
666fn parse_codec_expr(p: parse::ParseStream<'_>) -> Result<(Expr, Option<Error>)> {
681 let (maybe_type_path, punct_span) = maybe_type_path(p);
682 if maybe_type_path {
683 let helpful_error =
684 punct_span.map(|span| Error::new(span, "help: try inserting a `::` before this `<`"));
685 let mut type_path: TypePath = match p.parse() {
686 Ok(v) => v,
687 Err(mut e) => match helpful_error {
688 Some(help) => {
689 e.combine(help);
690 return Err(e);
691 }
692 None => return Err(e),
693 },
694 };
695 for segment in type_path.path.segments.iter_mut() {
698 match segment.arguments {
699 PathArguments::AngleBracketed(ref mut arguments) => {
700 let span = arguments.span();
701 arguments
702 .colon2_token
703 .get_or_insert_with(|| token::PathSep {
704 spans: [span, span],
705 });
706 }
707 _ => (),
708 }
709 }
710 Ok((
711 Expr::Path(ExprPath {
712 attrs: Vec::new(),
713 qself: type_path.qself,
714 path: type_path.path,
715 }),
716 helpful_error,
717 ))
718 } else {
719 p.parse().map(|x| (x, None))
720 }
721}
722
723fn parse_prefixed_name(
725 value: syn::parse::ParseStream<'_>,
726) -> Result<(Option<NamespaceRef>, NameRef)> {
727 if !value.peek(LitStr) {
728 return Ok((None, value.parse()?));
731 }
732
733 let name: LitStr = value.parse()?;
734 let name_span = name.span();
735 let (prefix, name) = match name
736 .value()
737 .try_into()
738 .and_then(|name: rxml_validation::Name| name.split_name())
739 {
740 Ok(v) => v,
741 Err(e) => {
742 return Err(Error::new(
743 name_span,
744 format!("not a valid XML name: {}", e),
745 ))
746 }
747 };
748 let name = NameRef::Literal {
749 value: name,
750 span: name_span,
751 };
752 if let Some(prefix) = prefix {
753 let namespace_uri = match prefix.as_str() {
754 "xml" => XMLNS_XML,
755 "xmlns" => XMLNS_XMLNS,
756 other => return Err(Error::new(
757 name_span,
758 format!("prefix `{}` is not a built-in prefix and cannot be used. specify the desired namespace using the `namespace` key instead.", other)
759 )),
760 };
761 Ok((Some(NamespaceRef::fudge(namespace_uri, name_span)), name))
762 } else {
763 Ok((None, name))
764 }
765}
766
767#[derive(Debug)]
769pub(crate) enum XmlFieldMeta {
770 Attribute {
772 span: Span,
776
777 qname: QNameRef,
779
780 default_: Flag,
782
783 type_: Option<Type>,
785
786 codec: Option<Expr>,
788 },
789
790 Text {
792 span: Span,
796
797 codec: Option<Expr>,
799
800 type_: Option<Type>,
802 },
803
804 Child {
806 span: Span,
810
811 default_: Flag,
813
814 amount: Option<AmountConstraint>,
816 },
817
818 Extract {
820 span: Span,
824
825 qname: QNameRef,
827
828 amount: Option<AmountConstraint>,
830
831 default_: Flag,
833
834 fields: Vec<XmlFieldMeta>,
836
837 on_unknown_attribute: Option<Ident>,
839
840 on_unknown_child: Option<Ident>,
842 },
843
844 Element {
846 span: Span,
850
851 default_: Flag,
853
854 amount: Option<AmountConstraint>,
856 },
857
858 Flag {
860 span: Span,
864
865 qname: QNameRef,
867 },
868}
869
870impl XmlFieldMeta {
871 fn attribute_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
878 if meta.input.peek(Token![=]) {
879 let (namespace, name) = parse_prefixed_name(meta.value()?)?;
881 Ok(Self::Attribute {
882 span: meta.path.span(),
883 qname: QNameRef {
884 name: Some(name),
885 namespace,
886 },
887 default_: Flag::Absent,
888 type_: None,
889 codec: None,
890 })
891 } else if meta.input.peek(syn::token::Paren) {
892 let mut qname = QNameRef::default();
894 let mut default_ = Flag::Absent;
895 let mut type_ = None;
896 let mut codec = None;
897 meta.parse_nested_meta(|meta| {
898 if meta.path.is_ident("default") {
899 if default_.is_set() {
900 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
901 }
902 default_ = (&meta.path).into();
903 Ok(())
904 } else if meta.path.is_ident("type_") {
905 if type_.is_some() {
906 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
907 }
908 type_ = Some(meta.value()?.parse()?);
909 Ok(())
910 } else if meta.path.is_ident("codec") {
911 if codec.is_some() {
912 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
913 }
914 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
915 let lookahead = meta.input.lookahead1();
918 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
919 if let Some(helpful_error) = helpful_error {
920 let mut e = lookahead.error();
921 e.combine(helpful_error);
922 return Err(e);
923 }
924 }
925 codec = Some(new_codec);
926 Ok(())
927 } else {
928 match qname.parse_incremental_from_meta(meta)? {
929 None => Ok(()),
930 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
931 }
932 }
933 })?;
934 Ok(Self::Attribute {
935 span: meta.path.span(),
936 qname,
937 default_,
938 type_,
939 codec,
940 })
941 } else {
942 Ok(Self::Attribute {
944 span: meta.path.span(),
945 qname: QNameRef::default(),
946 default_: Flag::Absent,
947 type_: None,
948 codec: None,
949 })
950 }
951 }
952
953 fn text_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
955 if meta.input.peek(Token![=]) {
956 let (codec, helpful_error) = parse_codec_expr(meta.value()?)?;
957 let lookahead = meta.input.lookahead1();
967 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
968 if let Some(helpful_error) = helpful_error {
969 let mut e = lookahead.error();
970 e.combine(helpful_error);
971 return Err(e);
972 }
973 }
974 Ok(Self::Text {
975 span: meta.path.span(),
976 type_: None,
977 codec: Some(codec),
978 })
979 } else if meta.input.peek(syn::token::Paren) {
980 let mut codec: Option<Expr> = None;
981 let mut type_: Option<Type> = None;
982 meta.parse_nested_meta(|meta| {
983 if meta.path.is_ident("codec") {
984 if codec.is_some() {
985 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
986 }
987 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
988 let lookahead = meta.input.lookahead1();
991 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
992 if let Some(helpful_error) = helpful_error {
993 let mut e = lookahead.error();
994 e.combine(helpful_error);
995 return Err(e);
996 }
997 }
998 codec = Some(new_codec);
999 Ok(())
1000 } else if meta.path.is_ident("type_") {
1001 if type_.is_some() {
1002 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
1003 }
1004 type_ = Some(meta.value()?.parse()?);
1005 Ok(())
1006 } else {
1007 Err(Error::new_spanned(meta.path, "unsupported key"))
1008 }
1009 })?;
1010 Ok(Self::Text {
1011 span: meta.path.span(),
1012 type_,
1013 codec,
1014 })
1015 } else {
1016 Ok(Self::Text {
1017 span: meta.path.span(),
1018 type_: None,
1019 codec: None,
1020 })
1021 }
1022 }
1023
1024 fn child_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1026 if meta.input.peek(syn::token::Paren) {
1027 let mut default_ = Flag::Absent;
1028 let mut amount = None;
1029 meta.parse_nested_meta(|meta| {
1030 if meta.path.is_ident("default") {
1031 if default_.is_set() {
1032 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1033 }
1034 default_ = (&meta.path).into();
1035 Ok(())
1036 } else if meta.path.is_ident("n") {
1037 if amount.is_some() {
1038 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1039 }
1040 amount = Some(meta.value()?.parse()?);
1041 Ok(())
1042 } else {
1043 Err(Error::new_spanned(meta.path, "unsupported key"))
1044 }
1045 })?;
1046 Ok(Self::Child {
1047 span: meta.path.span(),
1048 default_,
1049 amount,
1050 })
1051 } else {
1052 Ok(Self::Child {
1053 span: meta.path.span(),
1054 default_: Flag::Absent,
1055 amount: None,
1056 })
1057 }
1058 }
1059
1060 fn extract_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1062 let mut qname = QNameRef::default();
1063 let mut fields = None;
1064 let mut amount = None;
1065 let mut on_unknown_attribute = None;
1066 let mut on_unknown_child = None;
1067 let mut default_ = Flag::Absent;
1068 meta.parse_nested_meta(|meta| {
1069 if meta.path.is_ident("default") {
1070 if default_.is_set() {
1071 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1072 }
1073 default_ = (&meta.path).into();
1074 Ok(())
1075 } else if meta.path.is_ident("fields") {
1076 if let Some((fields_span, _)) = fields.as_ref() {
1077 let mut error = Error::new_spanned(meta.path, "duplicate `fields` meta");
1078 error.combine(Error::new(*fields_span, "previous `fields` meta was here"));
1079 return Err(error);
1080 }
1081 let mut new_fields = Vec::new();
1082 meta.parse_nested_meta(|meta| {
1083 new_fields.push(XmlFieldMeta::parse_from_meta(meta)?);
1084 Ok(())
1085 })?;
1086 fields = Some((meta.path.span(), new_fields));
1087 Ok(())
1088 } else if meta.path.is_ident("n") {
1089 if amount.is_some() {
1090 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1091 }
1092 amount = Some(meta.value()?.parse()?);
1093 Ok(())
1094 } else if meta.path.is_ident("on_unknown_attribute") {
1095 if on_unknown_attribute.is_some() {
1096 return Err(Error::new_spanned(
1097 meta.path,
1098 "duplicate `on_unknown_attribute` key",
1099 ));
1100 }
1101 on_unknown_attribute = Some(meta.value()?.parse()?);
1102 Ok(())
1103 } else if meta.path.is_ident("on_unknown_child") {
1104 if on_unknown_child.is_some() {
1105 return Err(Error::new_spanned(
1106 meta.path,
1107 "duplicate `on_unknown_child` key",
1108 ));
1109 }
1110 on_unknown_child = Some(meta.value()?.parse()?);
1111 Ok(())
1112 } else {
1113 match qname.parse_incremental_from_meta(meta)? {
1114 None => Ok(()),
1115 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1116 }
1117 }
1118 })?;
1119 let fields = fields.map(|(_, x)| x).unwrap_or_else(Vec::new);
1120 Ok(Self::Extract {
1121 span: meta.path.span(),
1122 default_,
1123 qname,
1124 fields,
1125 amount,
1126 on_unknown_attribute,
1127 on_unknown_child,
1128 })
1129 }
1130
1131 fn element_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1133 let mut amount = None;
1134 let mut default_ = Flag::Absent;
1135 if meta.input.peek(syn::token::Paren) {
1136 meta.parse_nested_meta(|meta| {
1137 if meta.path.is_ident("default") {
1138 if default_.is_set() {
1139 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1140 }
1141 default_ = (&meta.path).into();
1142 Ok(())
1143 } else if meta.path.is_ident("n") {
1144 if amount.is_some() {
1145 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1146 }
1147 amount = Some(meta.value()?.parse()?);
1148 Ok(())
1149 } else {
1150 Err(Error::new_spanned(meta.path, "unsupported key"))
1151 }
1152 })?;
1153 }
1154 Ok(Self::Element {
1155 span: meta.path.span(),
1156 default_,
1157 amount,
1158 })
1159 }
1160
1161 fn flag_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1163 let mut qname = QNameRef::default();
1164 if meta.input.peek(syn::token::Paren) {
1165 meta.parse_nested_meta(|meta| match qname.parse_incremental_from_meta(meta)? {
1166 None => Ok(()),
1167 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1168 })?;
1169 }
1170 Ok(Self::Flag {
1171 span: meta.path.span(),
1172 qname,
1173 })
1174 }
1175
1176 fn parse_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1179 if meta.path.is_ident("attribute") {
1180 Self::attribute_from_meta(meta)
1181 } else if meta.path.is_ident("text") {
1182 Self::text_from_meta(meta)
1183 } else if meta.path.is_ident("child") {
1184 Self::child_from_meta(meta)
1185 } else if meta.path.is_ident("extract") {
1186 Self::extract_from_meta(meta)
1187 } else if meta.path.is_ident("element") {
1188 Self::element_from_meta(meta)
1189 } else if meta.path.is_ident("flag") {
1190 Self::flag_from_meta(meta)
1191 } else {
1192 Err(Error::new_spanned(meta.path, "unsupported field meta"))
1193 }
1194 }
1195
1196 pub(crate) fn parse_from_attribute(attr: &Attribute) -> Result<Self> {
1209 let mut result: Option<Self> = None;
1210
1211 attr.parse_nested_meta(|meta| {
1212 if result.is_some() {
1213 return Err(Error::new_spanned(
1214 meta.path,
1215 "multiple field type specifiers are not supported",
1216 ));
1217 }
1218
1219 result = Some(Self::parse_from_meta(meta)?);
1220 Ok(())
1221 })?;
1222
1223 if let Some(result) = result {
1224 Ok(result)
1225 } else {
1226 Err(Error::new_spanned(
1227 attr,
1228 "missing field type specifier within `#[xml(..)]`",
1229 ))
1230 }
1231 }
1232
1233 pub(crate) fn parse_from_attributes(attrs: &[Attribute], err_span: &Span) -> Result<Self> {
1241 let mut result: Option<Self> = None;
1242 for attr in attrs {
1243 if !attr.path().is_ident("xml") {
1244 continue;
1245 }
1246
1247 if result.is_some() {
1248 return Err(Error::new_spanned(
1249 attr,
1250 "only one #[xml(..)] attribute per field allowed.",
1251 ));
1252 }
1253
1254 result = Some(Self::parse_from_attribute(attr)?);
1255 }
1256
1257 if let Some(result) = result {
1258 Ok(result)
1259 } else {
1260 Err(Error::new(*err_span, "missing #[xml(..)] meta on field"))
1261 }
1262 }
1263
1264 pub(crate) fn span(&self) -> Span {
1267 match self {
1268 Self::Attribute { ref span, .. } => *span,
1269 Self::Child { ref span, .. } => *span,
1270 Self::Text { ref span, .. } => *span,
1271 Self::Extract { ref span, .. } => *span,
1272 Self::Element { ref span, .. } => *span,
1273 Self::Flag { ref span, .. } => *span,
1274 }
1275 }
1276
1277 pub(crate) fn take_type(&mut self) -> Option<Type> {
1279 match self {
1280 Self::Attribute { ref mut type_, .. } => type_.take(),
1281 Self::Text { ref mut type_, .. } => type_.take(),
1282 _ => None,
1283 }
1284 }
1285}