1use core::fmt;
13use core::hash::{Hash, Hasher};
14
15use proc_macro2::{Span, TokenStream};
16use quote::{quote, quote_spanned};
17use syn::{meta::ParseNestedMeta, spanned::Spanned, *};
18
19use rxml_validation::NcName;
20
21use crate::error_message::PrettyPath;
22
23pub const XMLNS_XML: &str = "http://www.w3.org/XML/1998/namespace";
25pub const XMLNS_XMLNS: &str = "http://www.w3.org/2000/xmlns/";
27
28macro_rules! reject_key {
29 ($key:ident not on $not_allowed_on:literal $(only on $only_allowed_on:literal)?) => {
30 if let Some(ref $key) = $key {
31 #[allow(unused_imports)]
32 use syn::spanned::Spanned as _;
33 return Err(Error::new(
34 $key.span(),
35 concat!(
36 "`",
37 stringify!($key),
38 "` is not allowed on ",
39 $not_allowed_on,
40 $(
41 " (only on ",
42 $only_allowed_on,
43 ")",
44 )?
45 ),
46 ));
47 }
48 };
49
50 ($key:ident flag not on $not_allowed_on:literal $(only on $only_allowed_on:literal)?) => {
51 if let Flag::Present(ref $key) = $key {
52 return Err(Error::new(
53 *$key,
54 concat!(
55 "`",
56 stringify!($key),
57 "` is not allowed on ",
58 $not_allowed_on,
59 $(
60 " (only on ",
61 $only_allowed_on,
62 ")",
63 )?
64 ),
65 ));
66 }
67 };
68
69 ($key:ident vec not on $not_allowed_on:literal $(only on $only_allowed_on:literal)?) => {
70 if let Some(ref $key) = $key.first() {
71 return Err(Error::new(
72 $key.span(),
73 concat!(
74 "`",
75 stringify!($key),
76 "` is not allowed on ",
77 $not_allowed_on,
78 $(
79 " (only on ",
80 $only_allowed_on,
81 ")",
82 )?
83 ),
84 ));
85 }
86 };
87}
88
89pub(crate) use reject_key;
90
91#[derive(Debug, Clone, PartialEq, Eq, Hash)]
93pub(crate) enum NamespaceRef {
94 LitStr(LitStr),
96
97 Path(Path),
99}
100
101impl NamespaceRef {
102 pub(crate) fn fudge(value: &str, span: Span) -> Self {
103 Self::LitStr(LitStr::new(value, span))
104 }
105}
106
107impl fmt::Display for NamespaceRef {
108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109 match self {
110 Self::LitStr(s) => write!(f, "{}", s.value()),
111 Self::Path(ref p) => write!(f, "<{}>", PrettyPath(p)),
112 }
113 }
114}
115
116impl syn::parse::Parse for NamespaceRef {
117 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
118 if input.peek(syn::LitStr) {
119 Ok(Self::LitStr(input.parse()?))
120 } else {
121 Ok(Self::Path(input.parse()?))
122 }
123 }
124}
125
126impl quote::ToTokens for NamespaceRef {
127 fn to_tokens(&self, tokens: &mut TokenStream) {
128 match self {
129 Self::LitStr(ref lit) => lit.to_tokens(tokens),
130 Self::Path(ref path) => path.to_tokens(tokens),
131 }
132 }
133}
134
135#[derive(Debug, Clone)]
137pub(crate) enum NameRef {
138 Literal {
140 value: NcName,
142
143 span: Span,
145 },
146
147 Path(Path),
149}
150
151impl NameRef {
152 pub(crate) fn fudge(value: NcName, span: Span) -> Self {
153 Self::Literal { value, span }
154 }
155}
156
157impl fmt::Display for NameRef {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 match self {
160 Self::Literal { value, .. } => write!(f, "{}", value.as_str()),
161 Self::Path(ref p) => write!(f, "<{}>", PrettyPath(p)),
162 }
163 }
164}
165
166impl Hash for NameRef {
167 fn hash<H: Hasher>(&self, h: &mut H) {
168 match self {
169 Self::Literal { ref value, .. } => value.hash(h),
170 Self::Path(ref path) => path.hash(h),
171 }
172 }
173}
174
175impl PartialEq for NameRef {
176 fn eq(&self, other: &NameRef) -> bool {
177 match self {
178 Self::Literal {
179 value: ref my_value,
180 ..
181 } => match other {
182 Self::Literal {
183 value: ref other_value,
184 ..
185 } => my_value == other_value,
186 _ => false,
187 },
188 Self::Path(ref my_path) => match other {
189 Self::Path(ref other_path) => my_path == other_path,
190 _ => false,
191 },
192 }
193 }
194}
195
196impl Eq for NameRef {}
197
198impl syn::parse::Parse for NameRef {
199 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
200 if input.peek(syn::LitStr) {
201 let s: LitStr = input.parse()?;
202 let span = s.span();
203 match NcName::try_from(s.value()) {
204 Ok(value) => Ok(Self::Literal { value, span }),
205 Err(e) => Err(Error::new(span, format!("not a valid XML name: {}", e))),
206 }
207 } else {
208 let p: Path = input.parse()?;
209 Ok(Self::Path(p))
210 }
211 }
212}
213
214impl quote::ToTokens for NameRef {
215 fn to_tokens(&self, tokens: &mut TokenStream) {
216 match self {
217 Self::Literal { ref value, span } => {
218 let span = *span;
219 let value = value.as_str();
220 let value = quote_spanned! { span=> #value };
221 tokens.extend(quote! {
227 unsafe { ::xso::exports::rxml::NcNameStr::from_str_unchecked(#value) }
228 })
229 }
230 Self::Path(ref path) => path.to_tokens(tokens),
231 }
232 }
233}
234
235#[derive(Debug)]
241pub(crate) enum AmountConstraint {
242 #[allow(dead_code)]
244 FixedSingle(Span),
245
246 Any(Span),
248}
249
250impl syn::parse::Parse for AmountConstraint {
251 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
252 if input.peek(LitInt) && !input.peek2(token::DotDot) && !input.peek2(token::DotDotEq) {
253 let lit: LitInt = input.parse()?;
254 let value: usize = lit.base10_parse()?;
255 if value == 1 {
256 Ok(Self::FixedSingle(lit.span()))
257 } else {
258 Err(Error::new(lit.span(), "only `1` and `..` are allowed here"))
259 }
260 } else {
261 let p: PatRange = input.parse()?;
262 if let Some(attr) = p.attrs.first() {
263 return Err(Error::new_spanned(attr, "attributes not allowed here"));
264 }
265 if let Some(start) = p.start.as_ref() {
266 return Err(Error::new_spanned(
267 start,
268 "only full ranges (`..`) are allowed here",
269 ));
270 }
271 if let Some(end) = p.end.as_ref() {
272 return Err(Error::new_spanned(
273 end,
274 "only full ranges (`..`) are allowed here",
275 ));
276 }
277 Ok(Self::Any(p.span()))
278 }
279 }
280}
281
282#[derive(Clone, Copy, Debug)]
284pub(crate) enum Flag {
285 Absent,
287
288 Present(
290 #[allow(dead_code)]
295 Span,
296 ),
297}
298
299impl Flag {
300 pub(crate) fn is_set(&self) -> bool {
302 match self {
303 Self::Absent => false,
304 Self::Present(_) => true,
305 }
306 }
307
308 pub(crate) fn take(&mut self) -> Self {
310 let mut result = Flag::Absent;
311 core::mem::swap(&mut result, self);
312 result
313 }
314}
315
316impl<T: Spanned> From<T> for Flag {
317 fn from(other: T) -> Flag {
318 Flag::Present(other.span())
319 }
320}
321
322#[derive(Debug, Default, PartialEq, Eq, Hash)]
324pub(crate) struct QNameRef {
325 pub(crate) namespace: Option<NamespaceRef>,
327
328 pub(crate) name: Option<NameRef>,
330}
331
332impl QNameRef {
333 fn parse_incremental_from_meta<'x>(
341 &mut self,
342 meta: ParseNestedMeta<'x>,
343 ) -> Result<Option<ParseNestedMeta<'x>>> {
344 if meta.path.is_ident("name") {
345 if self.name.is_some() {
346 return Err(Error::new_spanned(meta.path, "duplicate `name` key"));
347 }
348 let value = meta.value()?;
349 let name_span = value.span();
350 let (new_namespace, new_name) = parse_prefixed_name(value)?;
351 if let Some(new_namespace) = new_namespace {
352 if let Some(namespace) = self.namespace.as_ref() {
353 let mut error = Error::new(
354 name_span,
355 "cannot combine `namespace` key with prefixed `name`",
356 );
357 error.combine(Error::new_spanned(namespace, "`namespace` was set here"));
358 return Err(error);
359 }
360 self.namespace = Some(new_namespace);
361 }
362 self.name = Some(new_name);
363 Ok(None)
364 } else if meta.path.is_ident("namespace") {
365 if self.namespace.is_some() {
366 return Err(Error::new_spanned(
367 meta.path,
368 "duplicate `namespace` key or `name` key has prefix",
369 ));
370 }
371 self.namespace = Some(meta.value()?.parse()?);
372 Ok(None)
373 } else {
374 Ok(Some(meta))
375 }
376 }
377}
378
379#[derive(Debug)]
381pub(crate) enum DiscardSpec {
382 Attribute {
384 span: Span,
388
389 qname: QNameRef,
392 },
393
394 Text {
396 span: Span,
400 },
401}
402
403impl DiscardSpec {
404 pub(crate) fn span(&self) -> Span {
405 match self {
406 Self::Attribute { ref span, .. } => *span,
407 Self::Text { ref span, .. } => *span,
408 }
409 }
410}
411
412impl TryFrom<XmlFieldMeta> for DiscardSpec {
413 type Error = syn::Error;
414
415 fn try_from(other: XmlFieldMeta) -> Result<Self> {
416 match other {
417 XmlFieldMeta::Attribute {
418 span,
419 kind: AttributeKind::Generic(qname),
420 default_,
421 type_,
422 codec,
423 } => {
424 reject_key!(default_ flag not on "discard specifications" only on "fields");
425 reject_key!(type_ not on "discard specifications" only on "fields");
426 reject_key!(codec not on "discard specifications" only on "fields");
427 Ok(Self::Attribute { span, qname })
428 }
429 XmlFieldMeta::Text { span, type_, codec } => {
430 reject_key!(type_ not on "discard specifications" only on "fields");
431 reject_key!(codec not on "discard specifications" only on "fields");
432 Ok(Self::Text { span })
433 }
434 other => Err(Error::new(
435 other.span(),
436 "cannot discard this kind of child",
437 )),
438 }
439 }
440}
441
442#[derive(Debug)]
444pub(crate) struct SpannedQNameRef {
445 pub span: Span,
447
448 pub qname: QNameRef,
450}
451
452impl SpannedQNameRef {
453 pub(crate) fn span(&self) -> Span {
454 self.span
455 }
456}
457
458#[derive(Debug)]
460pub(crate) struct XmlCompoundMeta {
461 pub(crate) span: Span,
465
466 pub(crate) qname: QNameRef,
469
470 pub(crate) debug: Flag,
472
473 pub(crate) builder: Option<Ident>,
475
476 pub(crate) iterator: Option<Ident>,
478
479 pub(crate) on_unknown_attribute: Option<Ident>,
482
483 pub(crate) on_unknown_child: Option<Ident>,
486
487 pub(crate) exhaustive: Flag,
489
490 pub(crate) transparent: Flag,
492
493 pub(crate) discard: Vec<DiscardSpec>,
495
496 pub(crate) deserialize_callback: Option<Path>,
498
499 pub(crate) attribute: Option<SpannedQNameRef>,
501
502 pub(crate) value: Option<LitStr>,
504}
505
506impl XmlCompoundMeta {
507 fn parse_from_attribute(attr: &Attribute) -> Result<Self> {
512 let mut qname = QNameRef::default();
513 let mut builder = None;
514 let mut iterator = None;
515 let mut on_unknown_attribute = None;
516 let mut on_unknown_child = None;
517 let mut debug = Flag::Absent;
518 let mut exhaustive = Flag::Absent;
519 let mut transparent = Flag::Absent;
520 let mut discard = Vec::new();
521 let mut deserialize_callback = None;
522 let mut attribute = None;
523 let mut value = None;
524
525 attr.parse_nested_meta(|meta| {
526 if meta.path.is_ident("debug") {
527 if debug.is_set() {
528 return Err(Error::new_spanned(meta.path, "duplicate `debug` key"));
529 }
530 debug = (&meta.path).into();
531 Ok(())
532 } else if meta.path.is_ident("builder") {
533 if builder.is_some() {
534 return Err(Error::new_spanned(meta.path, "duplicate `builder` key"));
535 }
536 builder = Some(meta.value()?.parse()?);
537 Ok(())
538 } else if meta.path.is_ident("iterator") {
539 if iterator.is_some() {
540 return Err(Error::new_spanned(meta.path, "duplicate `iterator` key"));
541 }
542 iterator = Some(meta.value()?.parse()?);
543 Ok(())
544 } else if meta.path.is_ident("on_unknown_attribute") {
545 if on_unknown_attribute.is_some() {
546 return Err(Error::new_spanned(
547 meta.path,
548 "duplicate `on_unknown_attribute` key",
549 ));
550 }
551 on_unknown_attribute = Some(meta.value()?.parse()?);
552 Ok(())
553 } else if meta.path.is_ident("on_unknown_child") {
554 if on_unknown_child.is_some() {
555 return Err(Error::new_spanned(
556 meta.path,
557 "duplicate `on_unknown_child` key",
558 ));
559 }
560 on_unknown_child = Some(meta.value()?.parse()?);
561 Ok(())
562 } else if meta.path.is_ident("exhaustive") {
563 if exhaustive.is_set() {
564 return Err(Error::new_spanned(meta.path, "duplicate `exhaustive` key"));
565 }
566 exhaustive = (&meta.path).into();
567 Ok(())
568 } else if meta.path.is_ident("transparent") {
569 if transparent.is_set() {
570 return Err(Error::new_spanned(meta.path, "duplicate `transparent` key"));
571 }
572 transparent = (&meta.path).into();
573 Ok(())
574 } else if meta.path.is_ident("discard") {
575 meta.parse_nested_meta(|meta| {
576 discard.push(XmlFieldMeta::parse_from_meta(meta)?.try_into()?);
577 Ok(())
578 })?;
579 Ok(())
580 } else if meta.path.is_ident("deserialize_callback") {
581 if deserialize_callback.is_some() {
582 return Err(Error::new_spanned(
583 meta.path,
584 "duplicate `deserialize_callback` key",
585 ));
586 }
587 deserialize_callback = Some(meta.value()?.parse()?);
588 Ok(())
589 } else if meta.path.is_ident("attribute") {
590 if attribute.is_some() {
591 return Err(Error::new_spanned(meta.path, "duplicate `attribute` key"));
592 }
593
594 let span = meta.path.span();
595 let qname = if meta.input.peek(Token![=]) {
596 let (namespace, name) = parse_prefixed_name(meta.value()?)?;
597 QNameRef {
598 name: Some(name),
599 namespace,
600 }
601 } else {
602 let mut qname = QNameRef::default();
603 meta.parse_nested_meta(|meta| {
604 match qname.parse_incremental_from_meta(meta)? {
605 None => Ok(()),
606 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
607 }
608 })?;
609 qname
610 };
611
612 attribute = Some(SpannedQNameRef { qname, span });
613 Ok(())
614 } else if meta.path.is_ident("value") {
615 if value.is_some() {
616 return Err(Error::new_spanned(meta.path, "duplicate `value` key"));
617 }
618 value = Some(meta.value()?.parse()?);
619 Ok(())
620 } else {
621 match qname.parse_incremental_from_meta(meta)? {
622 None => Ok(()),
623 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
624 }
625 }
626 })?;
627
628 Ok(Self {
629 span: attr.span(),
630 qname,
631 debug,
632 builder,
633 iterator,
634 on_unknown_attribute,
635 on_unknown_child,
636 exhaustive,
637 transparent,
638 discard,
639 deserialize_callback,
640 attribute,
641 value,
642 })
643 }
644
645 pub(crate) fn try_parse_from_attributes(attrs: &[Attribute]) -> Result<Option<Self>> {
656 let mut result = None;
657 for attr in attrs {
658 if !attr.path().is_ident("xml") {
659 continue;
660 }
661 if result.is_some() {
662 return Err(syn::Error::new_spanned(
663 attr.path(),
664 "only one #[xml(..)] per struct or enum variant allowed",
665 ));
666 }
667 result = Some(Self::parse_from_attribute(attr)?);
668 }
669 Ok(result)
670 }
671
672 pub(crate) fn parse_from_attributes(attrs: &[Attribute]) -> Result<Self> {
681 match Self::try_parse_from_attributes(attrs)? {
682 Some(v) => Ok(v),
683 None => Err(syn::Error::new(
684 Span::call_site(),
685 "#[xml(..)] attribute required on struct or enum variant",
686 )),
687 }
688 }
689}
690
691fn maybe_type_path(p: parse::ParseStream<'_>) -> (bool, Option<Span>) {
700 let cursor = if p.peek(token::PathSep) {
704 p.cursor().punct().unwrap().1.punct().unwrap().1
709 } else {
710 p.cursor()
712 };
713
714 let mut cursor = cursor;
718 loop {
719 let Some((_, new_cursor)) = cursor.ident() else {
722 return (false, None);
723 };
724 cursor = new_cursor;
725
726 let Some((punct, new_cursor)) = cursor.punct() else {
729 return (false, None);
730 };
731 cursor = new_cursor;
732
733 match punct.as_char() {
734 '<' => return (true, Some(punct.span())),
737
738 ':' => (),
740
741 _ => return (false, None),
745 }
746
747 let Some((punct, new_cursor)) = cursor.punct() else {
749 return (false, None);
750 };
751 cursor = new_cursor;
752
753 if punct.as_char() != ':' {
754 return (false, None);
756 }
757
758 }
764}
765
766fn parse_codec_expr(p: parse::ParseStream<'_>) -> Result<(Expr, Option<Error>)> {
781 let (maybe_type_path, punct_span) = maybe_type_path(p);
782 if maybe_type_path {
783 let helpful_error =
784 punct_span.map(|span| Error::new(span, "help: try inserting a `::` before this `<`"));
785 let mut type_path: TypePath = match p.parse() {
786 Ok(v) => v,
787 Err(mut e) => match helpful_error {
788 Some(help) => {
789 e.combine(help);
790 return Err(e);
791 }
792 None => return Err(e),
793 },
794 };
795 for segment in type_path.path.segments.iter_mut() {
798 if let PathArguments::AngleBracketed(ref mut arguments) = segment.arguments {
799 let span = arguments.span();
800 arguments.colon2_token.get_or_insert(token::PathSep {
801 spans: [span, span],
802 });
803 }
804 }
805 Ok((
806 Expr::Path(ExprPath {
807 attrs: Vec::new(),
808 qself: type_path.qself,
809 path: type_path.path,
810 }),
811 helpful_error,
812 ))
813 } else {
814 p.parse().map(|x| (x, None))
815 }
816}
817
818fn parse_prefixed_name(
820 value: syn::parse::ParseStream<'_>,
821) -> Result<(Option<NamespaceRef>, NameRef)> {
822 if !value.peek(LitStr) {
823 return Ok((None, value.parse()?));
826 }
827
828 let name: LitStr = value.parse()?;
829 let name_span = name.span();
830 let (prefix, name) = match name
831 .value()
832 .try_into()
833 .and_then(|name: rxml_validation::Name| name.split_name())
834 {
835 Ok(v) => v,
836 Err(e) => {
837 return Err(Error::new(
838 name_span,
839 format!("not a valid XML name: {}", e),
840 ))
841 }
842 };
843 let name = NameRef::Literal {
844 value: name,
845 span: name_span,
846 };
847 if let Some(prefix) = prefix {
848 let namespace_uri = match prefix.as_str() {
849 "xml" => XMLNS_XML,
850 "xmlns" => XMLNS_XMLNS,
851 other => return Err(Error::new(
852 name_span,
853 format!("prefix `{}` is not a built-in prefix and cannot be used. specify the desired namespace using the `namespace` key instead.", other)
854 )),
855 };
856 Ok((Some(NamespaceRef::fudge(namespace_uri, name_span)), name))
857 } else {
858 Ok((None, name))
859 }
860}
861
862#[derive(Debug)]
864pub(crate) enum AttributeKind {
865 Generic(QNameRef),
867
868 XmlLang,
870}
871
872#[derive(Debug)]
874pub(crate) enum XmlFieldMeta {
875 Attribute {
877 span: Span,
881
882 kind: AttributeKind,
884
885 default_: Flag,
887
888 type_: Option<Type>,
890
891 codec: Option<Expr>,
893 },
894
895 Text {
897 span: Span,
901
902 codec: Option<Expr>,
904
905 type_: Option<Type>,
907 },
908
909 Child {
911 span: Span,
915
916 default_: Flag,
918
919 amount: Option<AmountConstraint>,
921 },
922
923 Extract {
925 span: Span,
929
930 qname: QNameRef,
932
933 amount: Option<AmountConstraint>,
935
936 default_: Flag,
938
939 fields: Vec<XmlFieldMeta>,
941
942 on_unknown_attribute: Option<Ident>,
944
945 on_unknown_child: Option<Ident>,
947 },
948
949 Element {
951 span: Span,
955
956 default_: Flag,
958
959 amount: Option<AmountConstraint>,
961 },
962
963 Flag {
965 span: Span,
969
970 qname: QNameRef,
972 },
973}
974
975impl XmlFieldMeta {
976 fn attribute_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
983 if meta.input.peek(Token![=]) {
984 let (namespace, name) = parse_prefixed_name(meta.value()?)?;
986 Ok(Self::Attribute {
987 span: meta.path.span(),
988 kind: AttributeKind::Generic(QNameRef {
989 name: Some(name),
990 namespace,
991 }),
992 default_: Flag::Absent,
993 type_: None,
994 codec: None,
995 })
996 } else if meta.input.peek(syn::token::Paren) {
997 let mut qname = QNameRef::default();
999 let mut default_ = Flag::Absent;
1000 let mut type_ = None;
1001 let mut codec = None;
1002 meta.parse_nested_meta(|meta| {
1003 if meta.path.is_ident("default") {
1004 if default_.is_set() {
1005 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1006 }
1007 default_ = (&meta.path).into();
1008 Ok(())
1009 } else if meta.path.is_ident("type_") {
1010 if type_.is_some() {
1011 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
1012 }
1013 type_ = Some(meta.value()?.parse()?);
1014 Ok(())
1015 } else if meta.path.is_ident("codec") {
1016 if codec.is_some() {
1017 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
1018 }
1019 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
1020 let lookahead = meta.input.lookahead1();
1023 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
1024 if let Some(helpful_error) = helpful_error {
1025 let mut e = lookahead.error();
1026 e.combine(helpful_error);
1027 return Err(e);
1028 }
1029 }
1030 codec = Some(new_codec);
1031 Ok(())
1032 } else {
1033 match qname.parse_incremental_from_meta(meta)? {
1034 None => Ok(()),
1035 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1036 }
1037 }
1038 })?;
1039 Ok(Self::Attribute {
1040 span: meta.path.span(),
1041 kind: AttributeKind::Generic(qname),
1042 default_,
1043 type_,
1044 codec,
1045 })
1046 } else {
1047 Ok(Self::Attribute {
1049 span: meta.path.span(),
1050 kind: AttributeKind::Generic(QNameRef::default()),
1051 default_: Flag::Absent,
1052 type_: None,
1053 codec: None,
1054 })
1055 }
1056 }
1057
1058 fn text_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1060 if meta.input.peek(Token![=]) {
1061 let (codec, helpful_error) = parse_codec_expr(meta.value()?)?;
1062 let lookahead = meta.input.lookahead1();
1072 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
1073 if let Some(helpful_error) = helpful_error {
1074 let mut e = lookahead.error();
1075 e.combine(helpful_error);
1076 return Err(e);
1077 }
1078 }
1079 Ok(Self::Text {
1080 span: meta.path.span(),
1081 type_: None,
1082 codec: Some(codec),
1083 })
1084 } else if meta.input.peek(syn::token::Paren) {
1085 let mut codec: Option<Expr> = None;
1086 let mut type_: Option<Type> = None;
1087 meta.parse_nested_meta(|meta| {
1088 if meta.path.is_ident("codec") {
1089 if codec.is_some() {
1090 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
1091 }
1092 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
1093 let lookahead = meta.input.lookahead1();
1096 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
1097 if let Some(helpful_error) = helpful_error {
1098 let mut e = lookahead.error();
1099 e.combine(helpful_error);
1100 return Err(e);
1101 }
1102 }
1103 codec = Some(new_codec);
1104 Ok(())
1105 } else if meta.path.is_ident("type_") {
1106 if type_.is_some() {
1107 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
1108 }
1109 type_ = Some(meta.value()?.parse()?);
1110 Ok(())
1111 } else {
1112 Err(Error::new_spanned(meta.path, "unsupported key"))
1113 }
1114 })?;
1115 Ok(Self::Text {
1116 span: meta.path.span(),
1117 type_,
1118 codec,
1119 })
1120 } else {
1121 Ok(Self::Text {
1122 span: meta.path.span(),
1123 type_: None,
1124 codec: None,
1125 })
1126 }
1127 }
1128
1129 fn child_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1131 if meta.input.peek(syn::token::Paren) {
1132 let mut default_ = Flag::Absent;
1133 let mut amount = None;
1134 meta.parse_nested_meta(|meta| {
1135 if meta.path.is_ident("default") {
1136 if default_.is_set() {
1137 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1138 }
1139 default_ = (&meta.path).into();
1140 Ok(())
1141 } else if meta.path.is_ident("n") {
1142 if amount.is_some() {
1143 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1144 }
1145 amount = Some(meta.value()?.parse()?);
1146 Ok(())
1147 } else {
1148 Err(Error::new_spanned(meta.path, "unsupported key"))
1149 }
1150 })?;
1151 Ok(Self::Child {
1152 span: meta.path.span(),
1153 default_,
1154 amount,
1155 })
1156 } else {
1157 Ok(Self::Child {
1158 span: meta.path.span(),
1159 default_: Flag::Absent,
1160 amount: None,
1161 })
1162 }
1163 }
1164
1165 fn extract_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1167 let mut qname = QNameRef::default();
1168 let mut fields = None;
1169 let mut amount = None;
1170 let mut on_unknown_attribute = None;
1171 let mut on_unknown_child = None;
1172 let mut default_ = Flag::Absent;
1173 meta.parse_nested_meta(|meta| {
1174 if meta.path.is_ident("default") {
1175 if default_.is_set() {
1176 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1177 }
1178 default_ = (&meta.path).into();
1179 Ok(())
1180 } else if meta.path.is_ident("fields") {
1181 if let Some((fields_span, _)) = fields.as_ref() {
1182 let mut error = Error::new_spanned(meta.path, "duplicate `fields` meta");
1183 error.combine(Error::new(*fields_span, "previous `fields` meta was here"));
1184 return Err(error);
1185 }
1186 let mut new_fields = Vec::new();
1187 meta.parse_nested_meta(|meta| {
1188 new_fields.push(XmlFieldMeta::parse_from_meta(meta)?);
1189 Ok(())
1190 })?;
1191 fields = Some((meta.path.span(), new_fields));
1192 Ok(())
1193 } else if meta.path.is_ident("n") {
1194 if amount.is_some() {
1195 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1196 }
1197 amount = Some(meta.value()?.parse()?);
1198 Ok(())
1199 } else if meta.path.is_ident("on_unknown_attribute") {
1200 if on_unknown_attribute.is_some() {
1201 return Err(Error::new_spanned(
1202 meta.path,
1203 "duplicate `on_unknown_attribute` key",
1204 ));
1205 }
1206 on_unknown_attribute = Some(meta.value()?.parse()?);
1207 Ok(())
1208 } else if meta.path.is_ident("on_unknown_child") {
1209 if on_unknown_child.is_some() {
1210 return Err(Error::new_spanned(
1211 meta.path,
1212 "duplicate `on_unknown_child` key",
1213 ));
1214 }
1215 on_unknown_child = Some(meta.value()?.parse()?);
1216 Ok(())
1217 } else {
1218 match qname.parse_incremental_from_meta(meta)? {
1219 None => Ok(()),
1220 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1221 }
1222 }
1223 })?;
1224 let fields = fields.map(|(_, x)| x).unwrap_or_else(Vec::new);
1225 Ok(Self::Extract {
1226 span: meta.path.span(),
1227 default_,
1228 qname,
1229 fields,
1230 amount,
1231 on_unknown_attribute,
1232 on_unknown_child,
1233 })
1234 }
1235
1236 fn element_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1238 let mut amount = None;
1239 let mut default_ = Flag::Absent;
1240 if meta.input.peek(syn::token::Paren) {
1241 meta.parse_nested_meta(|meta| {
1242 if meta.path.is_ident("default") {
1243 if default_.is_set() {
1244 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1245 }
1246 default_ = (&meta.path).into();
1247 Ok(())
1248 } else if meta.path.is_ident("n") {
1249 if amount.is_some() {
1250 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1251 }
1252 amount = Some(meta.value()?.parse()?);
1253 Ok(())
1254 } else {
1255 Err(Error::new_spanned(meta.path, "unsupported key"))
1256 }
1257 })?;
1258 }
1259 Ok(Self::Element {
1260 span: meta.path.span(),
1261 default_,
1262 amount,
1263 })
1264 }
1265
1266 fn flag_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1268 let mut qname = QNameRef::default();
1269 if meta.input.peek(syn::token::Paren) {
1270 meta.parse_nested_meta(|meta| match qname.parse_incremental_from_meta(meta)? {
1271 None => Ok(()),
1272 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1273 })?;
1274 }
1275 Ok(Self::Flag {
1276 span: meta.path.span(),
1277 qname,
1278 })
1279 }
1280
1281 fn lang_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1283 let mut default_ = Flag::Absent;
1284 let mut type_ = None;
1285 let mut codec = None;
1286
1287 if meta.input.peek(syn::token::Paren) {
1288 meta.parse_nested_meta(|meta| {
1289 if meta.path.is_ident("default") {
1290 if default_.is_set() {
1291 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1292 }
1293 default_ = (&meta.path).into();
1294 Ok(())
1295 } else if meta.path.is_ident("type_") {
1296 if type_.is_some() {
1297 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
1298 }
1299 type_ = Some(meta.value()?.parse()?);
1300 Ok(())
1301 } else if meta.path.is_ident("codec") {
1302 if codec.is_some() {
1303 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
1304 }
1305 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
1306 let lookahead = meta.input.lookahead1();
1309 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
1310 if let Some(helpful_error) = helpful_error {
1311 let mut e = lookahead.error();
1312 e.combine(helpful_error);
1313 return Err(e);
1314 }
1315 }
1316 codec = Some(new_codec);
1317 Ok(())
1318 } else {
1319 Err(Error::new_spanned(meta.path, "unsupported key"))
1320 }
1321 })?;
1322 }
1323
1324 Ok(Self::Attribute {
1325 span: meta.path.span(),
1326 kind: AttributeKind::XmlLang,
1327 default_,
1328 type_,
1329 codec,
1330 })
1331 }
1332
1333 fn parse_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1336 if meta.path.is_ident("attribute") {
1337 Self::attribute_from_meta(meta)
1338 } else if meta.path.is_ident("text") {
1339 Self::text_from_meta(meta)
1340 } else if meta.path.is_ident("child") {
1341 Self::child_from_meta(meta)
1342 } else if meta.path.is_ident("extract") {
1343 Self::extract_from_meta(meta)
1344 } else if meta.path.is_ident("element") {
1345 Self::element_from_meta(meta)
1346 } else if meta.path.is_ident("flag") {
1347 Self::flag_from_meta(meta)
1348 } else if meta.path.is_ident("lang") {
1349 Self::lang_from_meta(meta)
1350 } else {
1351 Err(Error::new_spanned(meta.path, "unsupported field meta"))
1352 }
1353 }
1354
1355 pub(crate) fn parse_from_attribute(attr: &Attribute) -> Result<Self> {
1368 let mut result: Option<Self> = None;
1369
1370 attr.parse_nested_meta(|meta| {
1371 if result.is_some() {
1372 return Err(Error::new_spanned(
1373 meta.path,
1374 "multiple field type specifiers are not supported",
1375 ));
1376 }
1377
1378 result = Some(Self::parse_from_meta(meta)?);
1379 Ok(())
1380 })?;
1381
1382 if let Some(result) = result {
1383 Ok(result)
1384 } else {
1385 Err(Error::new_spanned(
1386 attr,
1387 "missing field type specifier within `#[xml(..)]`",
1388 ))
1389 }
1390 }
1391
1392 pub(crate) fn parse_from_attributes(attrs: &[Attribute], err_span: &Span) -> Result<Self> {
1400 let mut result: Option<Self> = None;
1401 for attr in attrs {
1402 if !attr.path().is_ident("xml") {
1403 continue;
1404 }
1405
1406 if result.is_some() {
1407 return Err(Error::new_spanned(
1408 attr,
1409 "only one #[xml(..)] attribute per field allowed.",
1410 ));
1411 }
1412
1413 result = Some(Self::parse_from_attribute(attr)?);
1414 }
1415
1416 if let Some(result) = result {
1417 Ok(result)
1418 } else {
1419 Err(Error::new(*err_span, "missing #[xml(..)] meta on field"))
1420 }
1421 }
1422
1423 pub(crate) fn span(&self) -> Span {
1426 match self {
1427 Self::Attribute { ref span, .. } => *span,
1428 Self::Child { ref span, .. } => *span,
1429 Self::Text { ref span, .. } => *span,
1430 Self::Extract { ref span, .. } => *span,
1431 Self::Element { ref span, .. } => *span,
1432 Self::Flag { ref span, .. } => *span,
1433 }
1434 }
1435
1436 pub(crate) fn take_type(&mut self) -> Option<Type> {
1438 match self {
1439 Self::Attribute { ref mut type_, .. } => type_.take(),
1440 Self::Text { ref mut type_, .. } => type_.take(),
1441 _ => None,
1442 }
1443 }
1444}