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 pub fn to_str_token_stream(&self) -> TokenStream {
157 match self {
158 Self::Literal { value, .. } => {
159 let value = value.as_str();
160 quote! {
161 #value
162 }
163 }
164 _ => {
165 let inner = quote::ToTokens::to_token_stream(self);
166 quote! { (#inner).as_str() }
167 }
168 }
169 }
170}
171
172impl fmt::Display for NameRef {
173 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174 match self {
175 Self::Literal { value, .. } => write!(f, "{}", value.as_str()),
176 Self::Path(ref p) => write!(f, "<{}>", PrettyPath(p)),
177 }
178 }
179}
180
181impl Hash for NameRef {
182 fn hash<H: Hasher>(&self, h: &mut H) {
183 match self {
184 Self::Literal { ref value, .. } => value.hash(h),
185 Self::Path(ref path) => path.hash(h),
186 }
187 }
188}
189
190impl PartialEq for NameRef {
191 fn eq(&self, other: &NameRef) -> bool {
192 match self {
193 Self::Literal {
194 value: ref my_value,
195 ..
196 } => match other {
197 Self::Literal {
198 value: ref other_value,
199 ..
200 } => my_value == other_value,
201 _ => false,
202 },
203 Self::Path(ref my_path) => match other {
204 Self::Path(ref other_path) => my_path == other_path,
205 _ => false,
206 },
207 }
208 }
209}
210
211impl Eq for NameRef {}
212
213impl syn::parse::Parse for NameRef {
214 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
215 if input.peek(syn::LitStr) {
216 let s: LitStr = input.parse()?;
217 let span = s.span();
218 match NcName::try_from(s.value()) {
219 Ok(value) => Ok(Self::Literal { value, span }),
220 Err(e) => Err(Error::new(span, format!("not a valid XML name: {}", e))),
221 }
222 } else {
223 let p: Path = input.parse()?;
224 Ok(Self::Path(p))
225 }
226 }
227}
228
229impl quote::ToTokens for NameRef {
230 fn to_tokens(&self, tokens: &mut TokenStream) {
231 match self {
232 Self::Literal { ref value, span } => {
233 let span = *span;
234 let value = value.as_str();
235 let value = quote_spanned! { span=> #value };
236 tokens.extend(quote! {
242 unsafe { ::xso::exports::rxml::NcNameStr::from_str_unchecked(#value) }
243 })
244 }
245 Self::Path(ref path) => path.to_tokens(tokens),
246 }
247 }
248}
249
250#[derive(Debug)]
256pub(crate) enum AmountConstraint {
257 #[allow(dead_code)]
259 FixedSingle(Span),
260
261 Any(Span),
263}
264
265impl syn::parse::Parse for AmountConstraint {
266 fn parse(input: syn::parse::ParseStream<'_>) -> Result<Self> {
267 if input.peek(LitInt) && !input.peek2(token::DotDot) && !input.peek2(token::DotDotEq) {
268 let lit: LitInt = input.parse()?;
269 let value: usize = lit.base10_parse()?;
270 if value == 1 {
271 Ok(Self::FixedSingle(lit.span()))
272 } else {
273 Err(Error::new(lit.span(), "only `1` and `..` are allowed here"))
274 }
275 } else {
276 let p: PatRange = input.parse()?;
277 if let Some(attr) = p.attrs.first() {
278 return Err(Error::new_spanned(attr, "attributes not allowed here"));
279 }
280 if let Some(start) = p.start.as_ref() {
281 return Err(Error::new_spanned(
282 start,
283 "only full ranges (`..`) are allowed here",
284 ));
285 }
286 if let Some(end) = p.end.as_ref() {
287 return Err(Error::new_spanned(
288 end,
289 "only full ranges (`..`) are allowed here",
290 ));
291 }
292 Ok(Self::Any(p.span()))
293 }
294 }
295}
296
297#[derive(Clone, Copy, Debug)]
299pub(crate) enum Flag {
300 Absent,
302
303 Present(
305 #[allow(dead_code)]
310 Span,
311 ),
312}
313
314impl Flag {
315 pub(crate) fn is_set(&self) -> bool {
317 match self {
318 Self::Absent => false,
319 Self::Present(_) => true,
320 }
321 }
322
323 pub(crate) fn take(&mut self) -> Self {
325 let mut result = Flag::Absent;
326 core::mem::swap(&mut result, self);
327 result
328 }
329}
330
331impl<T: Spanned> From<T> for Flag {
332 fn from(other: T) -> Flag {
333 Flag::Present(other.span())
334 }
335}
336
337#[derive(Debug, Default, PartialEq, Eq, Hash)]
339pub(crate) struct QNameRef {
340 pub(crate) namespace: Option<NamespaceRef>,
342
343 pub(crate) name: Option<NameRef>,
345}
346
347impl QNameRef {
348 fn parse_incremental_from_meta<'x>(
356 &mut self,
357 meta: ParseNestedMeta<'x>,
358 ) -> Result<Option<ParseNestedMeta<'x>>> {
359 if meta.path.is_ident("name") {
360 if self.name.is_some() {
361 return Err(Error::new_spanned(meta.path, "duplicate `name` key"));
362 }
363 let value = meta.value()?;
364 let name_span = value.span();
365 let (new_namespace, new_name) = parse_prefixed_name(value)?;
366 if let Some(new_namespace) = new_namespace {
367 if let Some(namespace) = self.namespace.as_ref() {
368 let mut error = Error::new(
369 name_span,
370 "cannot combine `namespace` key with prefixed `name`",
371 );
372 error.combine(Error::new_spanned(namespace, "`namespace` was set here"));
373 return Err(error);
374 }
375 self.namespace = Some(new_namespace);
376 }
377 self.name = Some(new_name);
378 Ok(None)
379 } else if meta.path.is_ident("namespace") {
380 if self.namespace.is_some() {
381 return Err(Error::new_spanned(
382 meta.path,
383 "duplicate `namespace` key or `name` key has prefix",
384 ));
385 }
386 self.namespace = Some(meta.value()?.parse()?);
387 Ok(None)
388 } else {
389 Ok(Some(meta))
390 }
391 }
392}
393
394#[derive(Debug)]
396pub(crate) enum DiscardSpec {
397 Attribute {
399 span: Span,
403
404 qname: QNameRef,
407 },
408
409 Text {
411 span: Span,
415 },
416}
417
418impl DiscardSpec {
419 pub(crate) fn span(&self) -> Span {
420 match self {
421 Self::Attribute { ref span, .. } => *span,
422 Self::Text { ref span, .. } => *span,
423 }
424 }
425}
426
427impl TryFrom<XmlFieldMeta> for DiscardSpec {
428 type Error = syn::Error;
429
430 fn try_from(other: XmlFieldMeta) -> Result<Self> {
431 match other {
432 XmlFieldMeta::Attribute {
433 span,
434 kind: AttributeKind::Generic(qname),
435 default_,
436 type_,
437 codec,
438 } => {
439 reject_key!(default_ flag not on "discard specifications" only on "fields");
440 reject_key!(type_ not on "discard specifications" only on "fields");
441 reject_key!(codec not on "discard specifications" only on "fields");
442 Ok(Self::Attribute { span, qname })
443 }
444 XmlFieldMeta::Text { span, type_, codec } => {
445 reject_key!(type_ not on "discard specifications" only on "fields");
446 reject_key!(codec not on "discard specifications" only on "fields");
447 Ok(Self::Text { span })
448 }
449 other => Err(Error::new(
450 other.span(),
451 "cannot discard this kind of child",
452 )),
453 }
454 }
455}
456
457#[derive(Debug)]
459pub(crate) struct SpannedQNameRef {
460 pub span: Span,
462
463 pub qname: QNameRef,
465}
466
467impl SpannedQNameRef {
468 pub(crate) fn span(&self) -> Span {
469 self.span
470 }
471}
472
473#[derive(Debug)]
475pub(crate) struct XmlCompoundMeta {
476 pub(crate) span: Span,
480
481 pub(crate) qname: QNameRef,
484
485 pub(crate) debug: Flag,
487
488 pub(crate) builder: Option<Ident>,
490
491 pub(crate) iterator: Option<Ident>,
493
494 pub(crate) on_unknown_attribute: Option<Ident>,
497
498 pub(crate) on_unknown_child: Option<Ident>,
501
502 pub(crate) exhaustive: Flag,
504
505 pub(crate) transparent: Flag,
507
508 pub(crate) discard: Vec<DiscardSpec>,
510
511 pub(crate) deserialize_callback: Option<Path>,
513
514 pub(crate) attribute: Option<SpannedQNameRef>,
516
517 pub(crate) value: Option<LitStr>,
519}
520
521impl XmlCompoundMeta {
522 fn parse_from_attribute(attr: &Attribute) -> Result<Self> {
527 let mut qname = QNameRef::default();
528 let mut builder = None;
529 let mut iterator = None;
530 let mut on_unknown_attribute = None;
531 let mut on_unknown_child = None;
532 let mut debug = Flag::Absent;
533 let mut exhaustive = Flag::Absent;
534 let mut transparent = Flag::Absent;
535 let mut discard = Vec::new();
536 let mut deserialize_callback = None;
537 let mut attribute = None;
538 let mut value = None;
539
540 attr.parse_nested_meta(|meta| {
541 if meta.path.is_ident("debug") {
542 if debug.is_set() {
543 return Err(Error::new_spanned(meta.path, "duplicate `debug` key"));
544 }
545 debug = (&meta.path).into();
546 Ok(())
547 } else if meta.path.is_ident("builder") {
548 if builder.is_some() {
549 return Err(Error::new_spanned(meta.path, "duplicate `builder` key"));
550 }
551 builder = Some(meta.value()?.parse()?);
552 Ok(())
553 } else if meta.path.is_ident("iterator") {
554 if iterator.is_some() {
555 return Err(Error::new_spanned(meta.path, "duplicate `iterator` key"));
556 }
557 iterator = Some(meta.value()?.parse()?);
558 Ok(())
559 } else if meta.path.is_ident("on_unknown_attribute") {
560 if on_unknown_attribute.is_some() {
561 return Err(Error::new_spanned(
562 meta.path,
563 "duplicate `on_unknown_attribute` key",
564 ));
565 }
566 on_unknown_attribute = Some(meta.value()?.parse()?);
567 Ok(())
568 } else if meta.path.is_ident("on_unknown_child") {
569 if on_unknown_child.is_some() {
570 return Err(Error::new_spanned(
571 meta.path,
572 "duplicate `on_unknown_child` key",
573 ));
574 }
575 on_unknown_child = Some(meta.value()?.parse()?);
576 Ok(())
577 } else if meta.path.is_ident("exhaustive") {
578 if exhaustive.is_set() {
579 return Err(Error::new_spanned(meta.path, "duplicate `exhaustive` key"));
580 }
581 exhaustive = (&meta.path).into();
582 Ok(())
583 } else if meta.path.is_ident("transparent") {
584 if transparent.is_set() {
585 return Err(Error::new_spanned(meta.path, "duplicate `transparent` key"));
586 }
587 transparent = (&meta.path).into();
588 Ok(())
589 } else if meta.path.is_ident("discard") {
590 meta.parse_nested_meta(|meta| {
591 discard.push(XmlFieldMeta::parse_from_meta(meta)?.try_into()?);
592 Ok(())
593 })?;
594 Ok(())
595 } else if meta.path.is_ident("deserialize_callback") {
596 if deserialize_callback.is_some() {
597 return Err(Error::new_spanned(
598 meta.path,
599 "duplicate `deserialize_callback` key",
600 ));
601 }
602 deserialize_callback = Some(meta.value()?.parse()?);
603 Ok(())
604 } else if meta.path.is_ident("attribute") {
605 if attribute.is_some() {
606 return Err(Error::new_spanned(meta.path, "duplicate `attribute` key"));
607 }
608
609 let span = meta.path.span();
610 let qname = if meta.input.peek(Token![=]) {
611 let (namespace, name) = parse_prefixed_name(meta.value()?)?;
612 QNameRef {
613 name: Some(name),
614 namespace,
615 }
616 } else {
617 let mut qname = QNameRef::default();
618 meta.parse_nested_meta(|meta| {
619 match qname.parse_incremental_from_meta(meta)? {
620 None => Ok(()),
621 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
622 }
623 })?;
624 qname
625 };
626
627 attribute = Some(SpannedQNameRef { qname, span });
628 Ok(())
629 } else if meta.path.is_ident("value") {
630 if value.is_some() {
631 return Err(Error::new_spanned(meta.path, "duplicate `value` key"));
632 }
633 value = Some(meta.value()?.parse()?);
634 Ok(())
635 } else {
636 match qname.parse_incremental_from_meta(meta)? {
637 None => Ok(()),
638 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
639 }
640 }
641 })?;
642
643 Ok(Self {
644 span: attr.span(),
645 qname,
646 debug,
647 builder,
648 iterator,
649 on_unknown_attribute,
650 on_unknown_child,
651 exhaustive,
652 transparent,
653 discard,
654 deserialize_callback,
655 attribute,
656 value,
657 })
658 }
659
660 pub(crate) fn try_parse_from_attributes(attrs: &[Attribute]) -> Result<Option<Self>> {
671 let mut result = None;
672 for attr in attrs {
673 if !attr.path().is_ident("xml") {
674 continue;
675 }
676 if result.is_some() {
677 return Err(syn::Error::new_spanned(
678 attr.path(),
679 "only one #[xml(..)] per struct or enum variant allowed",
680 ));
681 }
682 result = Some(Self::parse_from_attribute(attr)?);
683 }
684 Ok(result)
685 }
686
687 pub(crate) fn parse_from_attributes(attrs: &[Attribute]) -> Result<Self> {
696 match Self::try_parse_from_attributes(attrs)? {
697 Some(v) => Ok(v),
698 None => Err(syn::Error::new(
699 Span::call_site(),
700 "#[xml(..)] attribute required on struct or enum variant",
701 )),
702 }
703 }
704}
705
706fn maybe_type_path(p: parse::ParseStream<'_>) -> (bool, Option<Span>) {
715 let cursor = if p.peek(token::PathSep) {
719 p.cursor().punct().unwrap().1.punct().unwrap().1
724 } else {
725 p.cursor()
727 };
728
729 let mut cursor = cursor;
733 loop {
734 let Some((_, new_cursor)) = cursor.ident() else {
737 return (false, None);
738 };
739 cursor = new_cursor;
740
741 let Some((punct, new_cursor)) = cursor.punct() else {
744 return (false, None);
745 };
746 cursor = new_cursor;
747
748 match punct.as_char() {
749 '<' => return (true, Some(punct.span())),
752
753 ':' => (),
755
756 _ => return (false, None),
760 }
761
762 let Some((punct, new_cursor)) = cursor.punct() else {
764 return (false, None);
765 };
766 cursor = new_cursor;
767
768 if punct.as_char() != ':' {
769 return (false, None);
771 }
772
773 }
779}
780
781fn parse_codec_expr(p: parse::ParseStream<'_>) -> Result<(Expr, Option<Error>)> {
796 let (maybe_type_path, punct_span) = maybe_type_path(p);
797 if maybe_type_path {
798 let helpful_error =
799 punct_span.map(|span| Error::new(span, "help: try inserting a `::` before this `<`"));
800 let mut type_path: TypePath = match p.parse() {
801 Ok(v) => v,
802 Err(mut e) => match helpful_error {
803 Some(help) => {
804 e.combine(help);
805 return Err(e);
806 }
807 None => return Err(e),
808 },
809 };
810 for segment in type_path.path.segments.iter_mut() {
813 if let PathArguments::AngleBracketed(ref mut arguments) = segment.arguments {
814 let span = arguments.span();
815 arguments.colon2_token.get_or_insert(token::PathSep {
816 spans: [span, span],
817 });
818 }
819 }
820 Ok((
821 Expr::Path(ExprPath {
822 attrs: Vec::new(),
823 qself: type_path.qself,
824 path: type_path.path,
825 }),
826 helpful_error,
827 ))
828 } else {
829 p.parse().map(|x| (x, None))
830 }
831}
832
833fn parse_prefixed_name(
835 value: syn::parse::ParseStream<'_>,
836) -> Result<(Option<NamespaceRef>, NameRef)> {
837 if !value.peek(LitStr) {
838 return Ok((None, value.parse()?));
841 }
842
843 let name: LitStr = value.parse()?;
844 let name_span = name.span();
845 let (prefix, name) = match name
846 .value()
847 .try_into()
848 .and_then(|name: rxml_validation::Name| name.split_name())
849 {
850 Ok(v) => v,
851 Err(e) => {
852 return Err(Error::new(
853 name_span,
854 format!("not a valid XML name: {}", e),
855 ))
856 }
857 };
858 let name = NameRef::Literal {
859 value: name,
860 span: name_span,
861 };
862 if let Some(prefix) = prefix {
863 let namespace_uri = match prefix.as_str() {
864 "xml" => XMLNS_XML,
865 "xmlns" => XMLNS_XMLNS,
866 other => return Err(Error::new(
867 name_span,
868 format!("prefix `{}` is not a built-in prefix and cannot be used. specify the desired namespace using the `namespace` key instead.", other)
869 )),
870 };
871 Ok((Some(NamespaceRef::fudge(namespace_uri, name_span)), name))
872 } else {
873 Ok((None, name))
874 }
875}
876
877#[derive(Debug)]
879pub(crate) enum AttributeKind {
880 Generic(QNameRef),
882
883 XmlLang,
885}
886
887#[derive(Debug)]
889pub(crate) enum XmlFieldMeta {
890 Attribute {
892 span: Span,
896
897 kind: AttributeKind,
899
900 default_: Flag,
902
903 type_: Option<Type>,
905
906 codec: Option<Expr>,
908 },
909
910 Text {
912 span: Span,
916
917 codec: Option<Expr>,
919
920 type_: Option<Type>,
922 },
923
924 Child {
926 span: Span,
930
931 default_: Flag,
933
934 amount: Option<AmountConstraint>,
936 },
937
938 Extract {
940 span: Span,
944
945 qname: QNameRef,
947
948 amount: Option<AmountConstraint>,
950
951 default_: Flag,
953
954 fields: Vec<XmlFieldMeta>,
956
957 on_unknown_attribute: Option<Ident>,
959
960 on_unknown_child: Option<Ident>,
962 },
963
964 Element {
966 span: Span,
970
971 default_: Flag,
973
974 amount: Option<AmountConstraint>,
976 },
977
978 Flag {
980 span: Span,
984
985 qname: QNameRef,
987 },
988}
989
990impl XmlFieldMeta {
991 fn attribute_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
998 if meta.input.peek(Token![=]) {
999 let (namespace, name) = parse_prefixed_name(meta.value()?)?;
1001 Ok(Self::Attribute {
1002 span: meta.path.span(),
1003 kind: AttributeKind::Generic(QNameRef {
1004 name: Some(name),
1005 namespace,
1006 }),
1007 default_: Flag::Absent,
1008 type_: None,
1009 codec: None,
1010 })
1011 } else if meta.input.peek(syn::token::Paren) {
1012 let mut qname = QNameRef::default();
1014 let mut default_ = Flag::Absent;
1015 let mut type_ = None;
1016 let mut codec = None;
1017 meta.parse_nested_meta(|meta| {
1018 if meta.path.is_ident("default") {
1019 if default_.is_set() {
1020 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1021 }
1022 default_ = (&meta.path).into();
1023 Ok(())
1024 } else if meta.path.is_ident("type_") {
1025 if type_.is_some() {
1026 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
1027 }
1028 type_ = Some(meta.value()?.parse()?);
1029 Ok(())
1030 } else if meta.path.is_ident("codec") {
1031 if codec.is_some() {
1032 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
1033 }
1034 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
1035 let lookahead = meta.input.lookahead1();
1038 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
1039 if let Some(helpful_error) = helpful_error {
1040 let mut e = lookahead.error();
1041 e.combine(helpful_error);
1042 return Err(e);
1043 }
1044 }
1045 codec = Some(new_codec);
1046 Ok(())
1047 } else {
1048 match qname.parse_incremental_from_meta(meta)? {
1049 None => Ok(()),
1050 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1051 }
1052 }
1053 })?;
1054 Ok(Self::Attribute {
1055 span: meta.path.span(),
1056 kind: AttributeKind::Generic(qname),
1057 default_,
1058 type_,
1059 codec,
1060 })
1061 } else {
1062 Ok(Self::Attribute {
1064 span: meta.path.span(),
1065 kind: AttributeKind::Generic(QNameRef::default()),
1066 default_: Flag::Absent,
1067 type_: None,
1068 codec: None,
1069 })
1070 }
1071 }
1072
1073 fn text_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1075 if meta.input.peek(Token![=]) {
1076 let (codec, helpful_error) = parse_codec_expr(meta.value()?)?;
1077 let lookahead = meta.input.lookahead1();
1087 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
1088 if let Some(helpful_error) = helpful_error {
1089 let mut e = lookahead.error();
1090 e.combine(helpful_error);
1091 return Err(e);
1092 }
1093 }
1094 Ok(Self::Text {
1095 span: meta.path.span(),
1096 type_: None,
1097 codec: Some(codec),
1098 })
1099 } else if meta.input.peek(syn::token::Paren) {
1100 let mut codec: Option<Expr> = None;
1101 let mut type_: Option<Type> = None;
1102 meta.parse_nested_meta(|meta| {
1103 if meta.path.is_ident("codec") {
1104 if codec.is_some() {
1105 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
1106 }
1107 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
1108 let lookahead = meta.input.lookahead1();
1111 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
1112 if let Some(helpful_error) = helpful_error {
1113 let mut e = lookahead.error();
1114 e.combine(helpful_error);
1115 return Err(e);
1116 }
1117 }
1118 codec = Some(new_codec);
1119 Ok(())
1120 } else if meta.path.is_ident("type_") {
1121 if type_.is_some() {
1122 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
1123 }
1124 type_ = Some(meta.value()?.parse()?);
1125 Ok(())
1126 } else {
1127 Err(Error::new_spanned(meta.path, "unsupported key"))
1128 }
1129 })?;
1130 Ok(Self::Text {
1131 span: meta.path.span(),
1132 type_,
1133 codec,
1134 })
1135 } else {
1136 Ok(Self::Text {
1137 span: meta.path.span(),
1138 type_: None,
1139 codec: None,
1140 })
1141 }
1142 }
1143
1144 fn child_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1146 if meta.input.peek(syn::token::Paren) {
1147 let mut default_ = Flag::Absent;
1148 let mut amount = None;
1149 meta.parse_nested_meta(|meta| {
1150 if meta.path.is_ident("default") {
1151 if default_.is_set() {
1152 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1153 }
1154 default_ = (&meta.path).into();
1155 Ok(())
1156 } else if meta.path.is_ident("n") {
1157 if amount.is_some() {
1158 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1159 }
1160 amount = Some(meta.value()?.parse()?);
1161 Ok(())
1162 } else {
1163 Err(Error::new_spanned(meta.path, "unsupported key"))
1164 }
1165 })?;
1166 Ok(Self::Child {
1167 span: meta.path.span(),
1168 default_,
1169 amount,
1170 })
1171 } else {
1172 Ok(Self::Child {
1173 span: meta.path.span(),
1174 default_: Flag::Absent,
1175 amount: None,
1176 })
1177 }
1178 }
1179
1180 fn extract_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1182 let mut qname = QNameRef::default();
1183 let mut fields = None;
1184 let mut amount = None;
1185 let mut on_unknown_attribute = None;
1186 let mut on_unknown_child = None;
1187 let mut default_ = Flag::Absent;
1188 meta.parse_nested_meta(|meta| {
1189 if meta.path.is_ident("default") {
1190 if default_.is_set() {
1191 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1192 }
1193 default_ = (&meta.path).into();
1194 Ok(())
1195 } else if meta.path.is_ident("fields") {
1196 if let Some((fields_span, _)) = fields.as_ref() {
1197 let mut error = Error::new_spanned(meta.path, "duplicate `fields` meta");
1198 error.combine(Error::new(*fields_span, "previous `fields` meta was here"));
1199 return Err(error);
1200 }
1201 let mut new_fields = Vec::new();
1202 meta.parse_nested_meta(|meta| {
1203 new_fields.push(XmlFieldMeta::parse_from_meta(meta)?);
1204 Ok(())
1205 })?;
1206 fields = Some((meta.path.span(), new_fields));
1207 Ok(())
1208 } else if meta.path.is_ident("n") {
1209 if amount.is_some() {
1210 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1211 }
1212 amount = Some(meta.value()?.parse()?);
1213 Ok(())
1214 } else if meta.path.is_ident("on_unknown_attribute") {
1215 if on_unknown_attribute.is_some() {
1216 return Err(Error::new_spanned(
1217 meta.path,
1218 "duplicate `on_unknown_attribute` key",
1219 ));
1220 }
1221 on_unknown_attribute = Some(meta.value()?.parse()?);
1222 Ok(())
1223 } else if meta.path.is_ident("on_unknown_child") {
1224 if on_unknown_child.is_some() {
1225 return Err(Error::new_spanned(
1226 meta.path,
1227 "duplicate `on_unknown_child` key",
1228 ));
1229 }
1230 on_unknown_child = Some(meta.value()?.parse()?);
1231 Ok(())
1232 } else {
1233 match qname.parse_incremental_from_meta(meta)? {
1234 None => Ok(()),
1235 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1236 }
1237 }
1238 })?;
1239 let fields = fields.map(|(_, x)| x).unwrap_or_else(Vec::new);
1240 Ok(Self::Extract {
1241 span: meta.path.span(),
1242 default_,
1243 qname,
1244 fields,
1245 amount,
1246 on_unknown_attribute,
1247 on_unknown_child,
1248 })
1249 }
1250
1251 fn element_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1253 let mut amount = None;
1254 let mut default_ = Flag::Absent;
1255 if meta.input.peek(syn::token::Paren) {
1256 meta.parse_nested_meta(|meta| {
1257 if meta.path.is_ident("default") {
1258 if default_.is_set() {
1259 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1260 }
1261 default_ = (&meta.path).into();
1262 Ok(())
1263 } else if meta.path.is_ident("n") {
1264 if amount.is_some() {
1265 return Err(Error::new_spanned(meta.path, "duplicate `n` key"));
1266 }
1267 amount = Some(meta.value()?.parse()?);
1268 Ok(())
1269 } else {
1270 Err(Error::new_spanned(meta.path, "unsupported key"))
1271 }
1272 })?;
1273 }
1274 Ok(Self::Element {
1275 span: meta.path.span(),
1276 default_,
1277 amount,
1278 })
1279 }
1280
1281 fn flag_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1283 let mut qname = QNameRef::default();
1284 if meta.input.peek(syn::token::Paren) {
1285 meta.parse_nested_meta(|meta| match qname.parse_incremental_from_meta(meta)? {
1286 None => Ok(()),
1287 Some(meta) => Err(Error::new_spanned(meta.path, "unsupported key")),
1288 })?;
1289 }
1290 Ok(Self::Flag {
1291 span: meta.path.span(),
1292 qname,
1293 })
1294 }
1295
1296 fn lang_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1298 let mut default_ = Flag::Absent;
1299 let mut type_ = None;
1300 let mut codec = None;
1301
1302 if meta.input.peek(syn::token::Paren) {
1303 meta.parse_nested_meta(|meta| {
1304 if meta.path.is_ident("default") {
1305 if default_.is_set() {
1306 return Err(Error::new_spanned(meta.path, "duplicate `default` key"));
1307 }
1308 default_ = (&meta.path).into();
1309 Ok(())
1310 } else if meta.path.is_ident("type_") {
1311 if type_.is_some() {
1312 return Err(Error::new_spanned(meta.path, "duplicate `type_` key"));
1313 }
1314 type_ = Some(meta.value()?.parse()?);
1315 Ok(())
1316 } else if meta.path.is_ident("codec") {
1317 if codec.is_some() {
1318 return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
1319 }
1320 let (new_codec, helpful_error) = parse_codec_expr(meta.value()?)?;
1321 let lookahead = meta.input.lookahead1();
1324 if !lookahead.peek(Token![,]) && !meta.input.is_empty() {
1325 if let Some(helpful_error) = helpful_error {
1326 let mut e = lookahead.error();
1327 e.combine(helpful_error);
1328 return Err(e);
1329 }
1330 }
1331 codec = Some(new_codec);
1332 Ok(())
1333 } else {
1334 Err(Error::new_spanned(meta.path, "unsupported key"))
1335 }
1336 })?;
1337 }
1338
1339 Ok(Self::Attribute {
1340 span: meta.path.span(),
1341 kind: AttributeKind::XmlLang,
1342 default_,
1343 type_,
1344 codec,
1345 })
1346 }
1347
1348 fn parse_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
1351 if meta.path.is_ident("attribute") {
1352 Self::attribute_from_meta(meta)
1353 } else if meta.path.is_ident("text") {
1354 Self::text_from_meta(meta)
1355 } else if meta.path.is_ident("child") {
1356 Self::child_from_meta(meta)
1357 } else if meta.path.is_ident("extract") {
1358 Self::extract_from_meta(meta)
1359 } else if meta.path.is_ident("element") {
1360 Self::element_from_meta(meta)
1361 } else if meta.path.is_ident("flag") {
1362 Self::flag_from_meta(meta)
1363 } else if meta.path.is_ident("lang") {
1364 Self::lang_from_meta(meta)
1365 } else {
1366 Err(Error::new_spanned(meta.path, "unsupported field meta"))
1367 }
1368 }
1369
1370 pub(crate) fn parse_from_attribute(attr: &Attribute) -> Result<Self> {
1383 let mut result: Option<Self> = None;
1384
1385 attr.parse_nested_meta(|meta| {
1386 if result.is_some() {
1387 return Err(Error::new_spanned(
1388 meta.path,
1389 "multiple field type specifiers are not supported",
1390 ));
1391 }
1392
1393 result = Some(Self::parse_from_meta(meta)?);
1394 Ok(())
1395 })?;
1396
1397 if let Some(result) = result {
1398 Ok(result)
1399 } else {
1400 Err(Error::new_spanned(
1401 attr,
1402 "missing field type specifier within `#[xml(..)]`",
1403 ))
1404 }
1405 }
1406
1407 pub(crate) fn parse_from_attributes(attrs: &[Attribute], err_span: &Span) -> Result<Self> {
1415 let mut result: Option<Self> = None;
1416 for attr in attrs {
1417 if !attr.path().is_ident("xml") {
1418 continue;
1419 }
1420
1421 if result.is_some() {
1422 return Err(Error::new_spanned(
1423 attr,
1424 "only one #[xml(..)] attribute per field allowed.",
1425 ));
1426 }
1427
1428 result = Some(Self::parse_from_attribute(attr)?);
1429 }
1430
1431 if let Some(result) = result {
1432 Ok(result)
1433 } else {
1434 Err(Error::new(*err_span, "missing #[xml(..)] meta on field"))
1435 }
1436 }
1437
1438 pub(crate) fn span(&self) -> Span {
1441 match self {
1442 Self::Attribute { ref span, .. } => *span,
1443 Self::Child { ref span, .. } => *span,
1444 Self::Text { ref span, .. } => *span,
1445 Self::Extract { ref span, .. } => *span,
1446 Self::Element { ref span, .. } => *span,
1447 Self::Flag { ref span, .. } => *span,
1448 }
1449 }
1450
1451 pub(crate) fn take_type(&mut self) -> Option<Type> {
1453 match self {
1454 Self::Attribute { ref mut type_, .. } => type_.take(),
1455 Self::Text { ref mut type_, .. } => type_.take(),
1456 _ => None,
1457 }
1458 }
1459}