Skip to main content

xso_proc/
meta.rs

1// Copyright (c) 2024 Jonas Schäfer <jonas@zombofant.net>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7//! # Parse Rust attributes
8//!
9//! This module is concerned with parsing attributes from the Rust "meta"
10//! annotations on structs, enums, enum variants and fields.
11
12use 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
23/// XML core namespace URI (for the `xml:` prefix)
24pub const XMLNS_XML: &str = "http://www.w3.org/XML/1998/namespace";
25/// XML namespace URI (for the `xmlns:` prefix)
26pub 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/// Value for the `#[xml(namespace = ..)]` attribute.
92#[derive(Debug, Clone, PartialEq, Eq, Hash)]
93pub(crate) enum NamespaceRef {
94    /// The XML namespace is specified as a string literal.
95    LitStr(LitStr),
96
97    /// The XML namespace is specified as a path.
98    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/// Value for the `#[xml(name = .. )]` attribute.
136#[derive(Debug, Clone)]
137pub(crate) enum NameRef {
138    /// The XML name is specified as a string literal.
139    Literal {
140        /// The validated XML name.
141        value: NcName,
142
143        /// The span of the original [`syn::LitStr`].
144        span: Span,
145    },
146
147    /// The XML name is specified as a path.
148    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                // SAFETY: self.0 is a known-good NcName, so converting it to an
237                // NcNameStr is known to be safe.
238                // NOTE: we cannot use `quote_spanned! { self.span=> }` for the unsafe
239                // block as that would then in fact trip a `#[deny(unsafe_code)]` lint
240                // at the use site of the macro.
241                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/// Represents the amount constraint used with child elements.
251///
252/// Currently, this only supports "one" (literal `1`) or "any amount" (`..`).
253/// In the future, we might want to add support for any range pattern for
254/// `usize` and any positive integer literal.
255#[derive(Debug)]
256pub(crate) enum AmountConstraint {
257    /// Equivalent to `1`
258    #[allow(dead_code)]
259    FixedSingle(Span),
260
261    /// Equivalent to `..`.
262    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/// Represents a boolean flag from a `#[xml(..)]` attribute meta.
298#[derive(Clone, Copy, Debug)]
299pub(crate) enum Flag {
300    /// The flag is not set.
301    Absent,
302
303    /// The flag was set.
304    Present(
305        /// The span of the syntax element which enabled the flag.
306        ///
307        /// This is used to generate useful error messages by pointing at the
308        /// specific place the flag was activated.
309        #[allow(dead_code)]
310        Span,
311    ),
312}
313
314impl Flag {
315    /// Return true if the flag is set, false otherwise.
316    pub(crate) fn is_set(&self) -> bool {
317        match self {
318            Self::Absent => false,
319            Self::Present(_) => true,
320        }
321    }
322
323    /// Like `Option::take`, but for flags.
324    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/// A pair of `namespace` and `name` keys.
338#[derive(Debug, Default, PartialEq, Eq, Hash)]
339pub(crate) struct QNameRef {
340    /// The XML namespace supplied.
341    pub(crate) namespace: Option<NamespaceRef>,
342
343    /// The XML name supplied.
344    pub(crate) name: Option<NameRef>,
345}
346
347impl QNameRef {
348    /// Attempt to incrementally parse this QNameRef.
349    ///
350    /// If `meta` contains either `namespace` or `name` keys, they are
351    /// processed and either `Ok(None)` or an error is returned.
352    ///
353    /// If no matching key is found, `Ok(Some(meta))` is returned for further
354    /// processing.
355    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/// Identifies XML content to discard.
395#[derive(Debug)]
396pub(crate) enum DiscardSpec {
397    /// `#[xml(discard(attribute..))]`
398    Attribute {
399        /// The span of the nested meta from which this was parsed.
400        ///
401        /// This is useful for error messages.
402        span: Span,
403
404        /// The value assigned to `namespace` and `name` fields inside
405        /// `#[xml(discard(attribute(..)))]`, if any.
406        qname: QNameRef,
407    },
408
409    /// `#[xml(discard(text))]`
410    Text {
411        /// The span of the nested meta from which this was parsed.
412        ///
413        /// This is useful for error messages.
414        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/// Wrapper around `QNameRef` which saves additional span information.
458#[derive(Debug)]
459pub(crate) struct SpannedQNameRef {
460    /// The span which created the (potentially empty) ref.
461    pub span: Span,
462
463    /// The ref itself.
464    pub qname: QNameRef,
465}
466
467impl SpannedQNameRef {
468    pub(crate) fn span(&self) -> Span {
469        self.span
470    }
471}
472
473/// Contents of an `#[xml(..)]` attribute on a struct, enum variant, or enum.
474#[derive(Debug)]
475pub(crate) struct XmlCompoundMeta {
476    /// The span of the `#[xml(..)]` meta from which this was parsed.
477    ///
478    /// This is useful for error messages.
479    pub(crate) span: Span,
480
481    /// The value assigned to `namespace` and `name` fields inside
482    /// `#[xml(..)]`, if any.
483    pub(crate) qname: QNameRef,
484
485    /// The debug flag.
486    pub(crate) debug: Flag,
487
488    /// The value assigned to `builder` inside `#[xml(..)]`, if any.
489    pub(crate) builder: Option<Ident>,
490
491    /// The value assigned to `iterator` inside `#[xml(..)]`, if any.
492    pub(crate) iterator: Option<Ident>,
493
494    /// The value assigned to `on_unknown_attribute` inside `#[xml(..)]`, if
495    /// any.
496    pub(crate) on_unknown_attribute: Option<Ident>,
497
498    /// The value assigned to `on_unknown_child` inside `#[xml(..)]`, if
499    /// any.
500    pub(crate) on_unknown_child: Option<Ident>,
501
502    /// The exhaustive flag.
503    pub(crate) exhaustive: Flag,
504
505    /// The transparent flag.
506    pub(crate) transparent: Flag,
507
508    /// Items to discard.
509    pub(crate) discard: Vec<DiscardSpec>,
510
511    /// The value assigned to `deserialize_callback` inside `#[xml(..)]`, if any.
512    pub(crate) deserialize_callback: Option<Path>,
513
514    /// The value assigned to `attribute` inside `#[xml(..)]`, if any.
515    pub(crate) attribute: Option<SpannedQNameRef>,
516
517    /// The value assigned to `value` inside `#[xml(..)]`, if any.
518    pub(crate) value: Option<LitStr>,
519}
520
521impl XmlCompoundMeta {
522    /// Parse the meta values from a `#[xml(..)]` attribute.
523    ///
524    /// Undefined options or options with incompatible values are rejected
525    /// with an appropriate compile-time error.
526    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    /// Search through `attrs` for a single `#[xml(..)]` attribute and parse
661    /// it.
662    ///
663    /// Undefined options or options with incompatible values are rejected
664    /// with an appropriate compile-time error.
665    ///
666    /// If more than one `#[xml(..)]` attribute is found, an error is
667    /// emitted.
668    ///
669    /// If no `#[xml(..)]` attribute is found, `None` is returned.
670    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    /// Search through `attrs` for a single `#[xml(..)]` attribute and parse
688    /// it.
689    ///
690    /// Undefined options or options with incompatible values are rejected
691    /// with an appropriate compile-time error.
692    ///
693    /// If more than one or no `#[xml(..)]` attribute is found, an error is
694    /// emitted.
695    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
706/// Return true if the tokens the cursor points at are a valid type path
707/// prefix.
708///
709/// This does not advance the parse stream.
710///
711/// If the tokens *do* look like a type path, a Span which points at the first
712/// `<` encountered is returned. This can be used for a helpful error message
713/// in case parsing the type path does then fail.
714fn maybe_type_path(p: parse::ParseStream<'_>) -> (bool, Option<Span>) {
715    // ParseStream cursors do not advance the stream, but they are also rather
716    // unwieldy to use. Prepare for a lot of `let .. = ..`.
717
718    let cursor = if p.peek(token::PathSep) {
719        // If we have a path separator, we need to skip that initially. We
720        // do this by skipping two punctuations. We use unwrap() here because
721        // we already know for sure that we see two punctuation items (because
722        // of the peek).
723        p.cursor().punct().unwrap().1.punct().unwrap().1
724    } else {
725        // No `::` initially, so we just take what we have.
726        p.cursor()
727    };
728
729    // Now we loop over `$ident::` segments. If we find anything but a `:`
730    // after the ident, we exit. Depending on *what* we find, we either exit
731    // true or false, but see for yourself.
732    let mut cursor = cursor;
733    loop {
734        // Here we look for the identifier, but we do not care for its
735        // contents.
736        let Some((_, new_cursor)) = cursor.ident() else {
737            return (false, None);
738        };
739        cursor = new_cursor;
740
741        // Now we see what actually follows the ident (it must be punctuation
742        // for it to be a type path...)
743        let Some((punct, new_cursor)) = cursor.punct() else {
744            return (false, None);
745        };
746        cursor = new_cursor;
747
748        match punct.as_char() {
749            // Looks like a `foo<..`, we treat that as a type path for the
750            // reasons stated in [`parse_codec_expr`]'s doc.
751            '<' => return (true, Some(punct.span())),
752
753            // Continue looking ahead: looks like a path separator.
754            ':' => (),
755
756            // Anything else (such as `,` (separating another argument most
757            // likely), or `.` (a method call?)) we treat as "not a type
758            // path".
759            _ => return (false, None),
760        }
761
762        // If we are here, we saw a `:`. Look for the second one.
763        let Some((punct, new_cursor)) = cursor.punct() else {
764            return (false, None);
765        };
766        cursor = new_cursor;
767
768        if punct.as_char() != ':' {
769            // If it is not another `:`, it cannot be a type path.
770            return (false, None);
771        }
772
773        // And round and round and round it goes.
774        // We will terminate eventually because the cursor will return None
775        // on any of the lookups because parse streams are (hopefully!)
776        // finite. Most likely, we'll however encounter a `<` or other non-`:`
777        // punctuation first.
778    }
779}
780
781/// Parse expressions passed to `codec`.
782///
783/// Those will generally be paths to unit type constructors (such as `Foo`)
784/// or references to static values or chains of function calls.
785///
786/// In the case of unit type constructors for generic types, users may type
787/// for example `FixedHex<20>`, thinking they are writing a type path. However,
788/// while `FixedHex<20>` is indeed a valid type path, it is not a valid
789/// expression for a unit type constructor. Instead it is parsed as
790/// `FixedHex < 20` and then a syntax error.
791///
792/// We however know that `Foo < Bar` is never a valid expression for a type.
793/// Thus, we can be smart about this and inject the `::` at the right place
794/// automatically.
795fn 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        // We got a type path -- so we now inject the `::` before any `<` as
811        // needed.
812        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
833/// Parse an XML name while resolving built-in namespace prefixes.
834fn parse_prefixed_name(
835    value: syn::parse::ParseStream<'_>,
836) -> Result<(Option<NamespaceRef>, NameRef)> {
837    if !value.peek(LitStr) {
838        // if we don't have a string literal next, we delegate to the default
839        // `NameRef` parser.
840        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/// XML attribute subtypes for `#[xml(attribute)]` and `#[xml(lang)]`.
878#[derive(Debug)]
879pub(crate) enum AttributeKind {
880    /// Any generic attribute (`#[xml(attribute)]`).
881    Generic(QNameRef),
882
883    /// The special `xml:lang` attribute (`#[xml(lang)]`).
884    XmlLang,
885}
886
887/// Contents of an `#[xml(..)]` attribute on a struct or enum variant member.
888#[derive(Debug)]
889pub(crate) enum XmlFieldMeta {
890    /// `#[xml(attribute)]`, `#[xml(attribute = ..)]` or `#[xml(attribute(..))]`, `#[xml(lang)]`
891    Attribute {
892        /// The span of the `#[xml(attribute)]` meta from which this was parsed.
893        ///
894        /// This is useful for error messages.
895        span: Span,
896
897        /// Attribute subtype (normal vs. `xml:lang`).
898        kind: AttributeKind,
899
900        /// The `default` flag.
901        default_: Flag,
902
903        /// An explicit type override, only usable within extracts.
904        type_: Option<Type>,
905
906        /// The path to the optional codec type.
907        codec: Option<Expr>,
908    },
909
910    /// `#[xml(text)]`
911    Text {
912        /// The span of the `#[xml(text)]` meta from which this was parsed.
913        ///
914        /// This is useful for error messages.
915        span: Span,
916
917        /// The path to the optional codec type.
918        codec: Option<Expr>,
919
920        /// An explicit type override, only usable within extracts.
921        type_: Option<Type>,
922    },
923
924    /// `#[xml(child)`
925    Child {
926        /// The span of the `#[xml(child)]` meta from which this was parsed.
927        ///
928        /// This is useful for error messages.
929        span: Span,
930
931        /// The `default` flag.
932        default_: Flag,
933
934        /// The `n` flag.
935        amount: Option<AmountConstraint>,
936    },
937
938    /// `#[xml(extract)]
939    Extract {
940        /// The span of the `#[xml(extract)]` meta from which this was parsed.
941        ///
942        /// This is useful for error messages.
943        span: Span,
944
945        /// The namespace/name keys.
946        qname: QNameRef,
947
948        /// The `n` flag.
949        amount: Option<AmountConstraint>,
950
951        /// The `default` flag.
952        default_: Flag,
953
954        /// The `fields` nested meta.
955        fields: Vec<XmlFieldMeta>,
956
957        /// The `on_unknown_attribute` value.
958        on_unknown_attribute: Option<Ident>,
959
960        /// The `on_unknown_child` value.
961        on_unknown_child: Option<Ident>,
962    },
963
964    /// `#[xml(element)]`
965    Element {
966        /// The span of the `#[xml(element)]` meta from which this was parsed.
967        ///
968        /// This is useful for error messages.
969        span: Span,
970
971        /// The `default` flag.
972        default_: Flag,
973
974        /// The `n` flag.
975        amount: Option<AmountConstraint>,
976    },
977
978    /// `#[xml(flag)]
979    Flag {
980        /// The span of the `#[xml(flag)]` meta from which this was parsed.
981        ///
982        /// This is useful for error messages.
983        span: Span,
984
985        /// The namespace/name keys.
986        qname: QNameRef,
987    },
988}
989
990impl XmlFieldMeta {
991    /// Parse a `#[xml(attribute(..))]` meta.
992    ///
993    /// That meta can have three distinct syntax styles:
994    /// - argument-less: `#[xml(attribute)]`
995    /// - shorthand: `#[xml(attribute = ..)]`
996    /// - full: `#[xml(attribute(..))]`
997    fn attribute_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
998        if meta.input.peek(Token![=]) {
999            // shorthand syntax
1000            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            // full syntax
1013            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                    // See the comment at the top of text_from_meta() below for why we
1036                    // do this.
1037                    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            // argument-less syntax
1063            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    /// Parse a `#[xml(text)]` meta.
1074    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            // A meta value can only be followed by either a `,`, or the end
1078            // of the parse stream (because of the delimited group ending).
1079            // Hence we check we are there. And if we are *not* there, we emit
1080            // an error straight away, with the helpful addition from the
1081            // `parse_codec_expr` if we have it.
1082            //
1083            // If we do not do this, the user gets a rather confusing
1084            // "expected `,`" message if the `maybe_type_path` guess was
1085            // wrong.
1086            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                    // See above (at the top-ish of this function) for why we
1109                    // do this.
1110                    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    /// Parse a `#[xml(child)]` meta.
1145    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    /// Parse a `#[xml(extract)]` meta.
1181    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    /// Parse a `#[xml(element)]` meta.
1252    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    /// Parse a `#[xml(flag)]` meta.
1282    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    /// Parse a `#[xml(lang)]` meta.
1297    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                    // See the comment at the top of text_from_meta() below for why we
1322                    // do this.
1323                    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    /// Parse [`Self`] from a nestd meta, switching on the identifier
1349    /// of that nested meta.
1350    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    /// Parse an `#[xml(..)]` meta on a field.
1371    ///
1372    /// This switches based on the first identifier within the `#[xml(..)]`
1373    /// meta and generates an enum variant accordingly.
1374    ///
1375    /// Only a single nested meta is allowed; more than one will be
1376    /// rejected with an appropriate compile-time error.
1377    ///
1378    /// If no meta is contained at all, a compile-time error is generated.
1379    ///
1380    /// Undefined options or options with incompatible values are rejected
1381    /// with an appropriate compile-time error.
1382    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    /// Find and parse a `#[xml(..)]` meta on a field.
1408    ///
1409    /// This invokes [`Self::parse_from_attribute`] internally on the first
1410    /// encountered `#[xml(..)]` meta.
1411    ///
1412    /// If not exactly one `#[xml(..)]` meta is encountered, an error is
1413    /// returned. The error is spanned to `err_span`.
1414    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    /// Return a span which points at the meta which constructed this
1439    /// XmlFieldMeta.
1440    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    /// Extract an explicit type specification if it exists.
1452    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}