Skip to main content

darling_core/
from_meta.rs

1use quote::ToTokens;
2use std::borrow::Cow;
3use std::cell::RefCell;
4use std::collections::btree_map::BTreeMap;
5use std::collections::hash_map::HashMap;
6use std::collections::HashSet;
7use std::hash::BuildHasher;
8use std::num;
9use std::rc::Rc;
10use std::sync::atomic::AtomicBool;
11use std::sync::Arc;
12use syn::spanned::Spanned;
13
14use syn::{Expr, Ident, Lit, Meta, Path};
15
16use crate::ast::{MetaNameValueInvalidExpr, NestedMeta};
17use crate::util::path_to_string;
18use crate::{Error, Result};
19
20/// Create an instance from an item in an attribute declaration.
21///
22/// # Implementing `FromMeta`
23/// * Do not take a dependency on the `ident` of the passed-in meta item. The ident will be set by the field name of the containing struct.
24/// * Implement only the `from_*` methods that you intend to support. The default implementations will return useful errors.
25///
26/// # Provided Implementations
27/// ## bool
28///
29/// * Word with no value specified - becomes `true`.
30/// * As a boolean literal, e.g. `foo = true`.
31/// * As a string literal, e.g. `foo = "true"`.
32///
33/// ## char
34/// * As a char literal, e.g. `foo = '#'`.
35/// * As a string literal consisting of a single character, e.g. `foo = "#"`.
36///
37/// ## String
38/// * As a string literal, e.g. `foo = "hello"`.
39/// * As a raw string literal, e.g. `foo = r#"hello "world""#`.
40///
41/// ## Number
42/// * As a string literal, e.g. `foo = "-25"`.
43/// * As an unquoted positive value, e.g. `foo = 404`. Negative numbers must be in quotation marks.
44///
45/// ## ()
46/// * Word with no value specified, e.g. `foo`. This is best used with `Option`.
47///   See `darling::util::Flag` for a more strongly-typed alternative.
48///
49/// ## Option
50/// * Any format produces `Some`.
51///
52/// ## `Result<T, darling::Error>`
53/// * Allows for fallible parsing; will populate the target field with the result of the
54///   parse attempt.
55pub trait FromMeta: Sized {
56    fn from_nested_meta(item: &NestedMeta) -> Result<Self> {
57        (match *item {
58            NestedMeta::Lit(ref lit) => Self::from_value(lit),
59            NestedMeta::Meta(ref mi) => Self::from_meta(mi),
60            NestedMeta::NameValueInvalidExpr(ref meta) => Self::from_invalid_expr(meta),
61        })
62        .map_err(|e| e.with_span(item))
63    }
64
65    /// Create an instance from a `syn::Meta` by dispatching to the format-appropriate
66    /// trait function. This generally should not be overridden by implementers.
67    ///
68    /// # Error Spans
69    /// If this method is overridden and can introduce errors that weren't passed up from
70    /// other `from_meta` calls, the override must call `with_span` on the error using the
71    /// `item` to make sure that the emitted diagnostic points to the correct location in
72    /// source code.
73    fn from_meta(item: &Meta) -> Result<Self> {
74        (match *item {
75            Meta::Path(_) => Self::from_word(),
76            Meta::List(ref value) => {
77                Self::from_list(&NestedMeta::parse_meta_list(value.tokens.clone())?[..])
78            }
79            Meta::NameValue(ref value) => Self::from_expr(&value.value),
80        })
81        .map_err(|e| e.with_span(item))
82    }
83
84    /// When a field is omitted from a parent meta-item, `from_none` is used to attempt
85    /// recovery before a missing field error is generated.
86    ///
87    /// **Most types should not override this method.** `darling` already allows field-level
88    /// missing-field recovery using `#[darling(default)]` and `#[darling(default = "...")]`,
89    /// and users who add a `String` field to their `FromMeta`-deriving struct would be surprised
90    /// if they get back `""` instead of a missing field error when that field is omitted.
91    ///
92    /// The primary use-case for this is `Option<T>` fields gracefully handling absence without
93    /// needing `#[darling(default)]`.
94    fn from_none() -> Option<Self> {
95        None
96    }
97
98    /// Create an instance from the presence of the word in the attribute with no
99    /// additional options specified.
100    fn from_word() -> Result<Self> {
101        Err(Error::unsupported_format("word"))
102    }
103
104    /// Create an instance from a list of nested meta items.
105    #[allow(unused_variables)]
106    fn from_list(items: &[NestedMeta]) -> Result<Self> {
107        Err(Error::unsupported_format("list"))
108    }
109
110    /// Create an instance from a literal value of either `foo = "bar"` or `foo("bar")`.
111    /// This dispatches to the appropriate method based on the type of literal encountered,
112    /// and generally should not be overridden by implementers.
113    ///
114    /// # Error Spans
115    /// If this method is overridden, the override must make sure to add `value`'s span
116    /// information to the returned error by calling `with_span(value)` on the `Error` instance.
117    fn from_value(value: &Lit) -> Result<Self> {
118        (match *value {
119            Lit::Bool(ref b) => Self::from_bool(b.value),
120            Lit::Str(ref s) => Self::from_string(&s.value()),
121            Lit::Char(ref ch) => Self::from_char(ch.value()),
122            _ => Err(Error::unexpected_lit_type(value)),
123        })
124        .map_err(|e| e.with_span(value))
125    }
126
127    fn from_expr(expr: &Expr) -> Result<Self> {
128        match *expr {
129            Expr::Lit(ref lit) => Self::from_value(&lit.lit),
130            Expr::Group(ref group) => {
131                // syn may generate this invisible group delimiter when the input to the darling
132                // proc macro (specifically, the attributes) are generated by a
133                // macro_rules! (e.g. propagating a macro_rules!'s expr)
134                // Since we want to basically ignore these invisible group delimiters,
135                // we just propagate the call to the inner expression.
136                Self::from_expr(&group.expr)
137            }
138            _ => Err(Error::unexpected_expr_type(expr)),
139        }
140        .map_err(|e| e.with_span(expr))
141    }
142
143    /// `name = value` where the `value` failed to parse as a [`syn::Expr`].
144    ///
145    /// For example:
146    ///
147    /// ```ignore
148    /// #[example(vis = pub(crate))]
149    /// #[example(bound = where T: Deserialize<'de>)]
150    /// ```
151    ///
152    /// It is recommended to implement [`syn::parse::Parse`] for your type, then
153    /// have an implementation of `from_invalid_expr` as follows:
154    ///
155    /// ```ignore
156    /// fn from_invalid_expr(value: &MetaNameValueInvalidExpr) -> darling::Result<Self> {
157    ///     syn::parse2(value.value.clone()).map_err(Into::into)
158    /// }
159    /// ```
160    ///
161    /// # Convert from anything
162    ///
163    /// This function handles parsing for things that are invalid expressions.
164    ///
165    /// Because of that, if you were to try and re-implement `impl FromMeta for syn::Type`,
166    /// you will run into a problem: `(i32, u32)` is both a valid [`Expr`]
167    /// and a valid [`Type`](syn::Type). `from_invalid_expr` will never be called for it, because it
168    /// **is** a valid expression.
169    ///
170    /// In order to circumvent that, you need to implement both `from_expr` and `from_invalid_expr`:
171    ///
172    /// ```ignore
173    /// fn from_expr(expr: &Expr) -> darling::Result<Self> {
174    ///     match *expr {
175    ///         // Invisible delimiter when the input to the macro is passed
176    ///         // by a `macro_rules!`, but we can safely ignore the wrapper
177    ///         Expr::Group(ref group) => Self::from_expr(&group.expr),
178    ///         _ => Ok(syn::parse2(expr.into_token_stream().clone())?)
179    ///     }
180    ///     .map_err(|e| e.with_span(expr))
181    /// }
182    ///
183    /// fn from_invalid_expr(value: &MetaNameValueInvalidExpr) -> darling::Result<Type> {
184    ///     syn::parse2(value.value.clone()).map_err(Into::into)
185    /// }
186    /// ```
187    ///
188    /// `from_expr` parses the set of all valid expressions, `from_invalid_expr` parses the set of all invalid expressions:
189    /// together, they can parse anything!
190    ///
191    /// # Truly arbitrary inputs
192    ///
193    /// Tokens are collected until the first comma is encountered. The comma is excluded
194    /// from the collected tokens.
195    ///
196    /// For this input, it means we first collect everything between `=` and `,` into a `TokenStream`:
197    ///
198    /// ```ignore
199    /// #[example(bound = where T: Deserialize<'de>, D: 'static)]
200    ///                   ^^^^^^^^^^^^^^^^^^^^^^^^^
201    /// ```
202    ///
203    /// Then we try to parse the remaining as a [`syn::NestedMeta`], and fail:
204    ///
205    /// ```ignore
206    /// #[example(bound = where T: Deserialize<'de>, D: 'static)]
207    ///                                              ^^^^^^^^^^
208    /// ```
209    ///
210    /// In order to support truly arbitrary inputs like the `bound` above, you can hold
211    /// the tokens in a string literal:
212    ///
213    /// ```ignore
214    /// #[example(bound = "where T: Deserialize<'de>, D: 'static")]
215    /// ```
216    ///
217    /// Then parse
218    fn from_invalid_expr(value: &MetaNameValueInvalidExpr) -> Result<Self> {
219        Err(value.error.clone())
220    }
221
222    /// Create an instance from a char literal in a value position.
223    #[allow(unused_variables)]
224    fn from_char(value: char) -> Result<Self> {
225        Err(Error::unexpected_type("char"))
226    }
227
228    /// Create an instance from a string literal in a value position.
229    #[allow(unused_variables)]
230    fn from_string(value: &str) -> Result<Self> {
231        Err(Error::unexpected_type("string"))
232    }
233
234    /// Create an instance from a bool literal in a value position.
235    #[allow(unused_variables)]
236    fn from_bool(value: bool) -> Result<Self> {
237        Err(Error::unexpected_type("bool"))
238    }
239}
240
241// FromMeta impls for std and syn types.
242
243impl FromMeta for () {
244    fn from_word() -> Result<Self> {
245        Ok(())
246    }
247
248    fn from_list(items: &[NestedMeta]) -> Result<Self> {
249        let mut errors = Error::accumulator();
250        for item in items {
251            errors.push(match item {
252                // Use `unknown_field_path` rather than `too_many_items` so that when this is used with
253                // `flatten` the resulting error message will include the valid fields rather than a confusing
254                // message about having only expected zero items.
255                //
256                // The accumulator is used to ensure all these errors are returned at once, rather than
257                // only producing an error on the first unexpected field in the flattened list.
258                NestedMeta::Meta(meta) => Error::unknown_field_path(meta.path()).with_span(meta),
259                NestedMeta::NameValueInvalidExpr(meta) => {
260                    Error::unknown_field_path(&meta.path).with_span(&meta.path.span())
261                }
262                NestedMeta::Lit(lit) => {
263                    Error::unexpected_expr_type(&syn::Expr::Lit(syn::ExprLit {
264                        attrs: vec![],
265                        lit: lit.clone(),
266                    }))
267                    .with_span(lit)
268                }
269            });
270        }
271
272        errors.finish()
273    }
274}
275
276impl FromMeta for bool {
277    fn from_word() -> Result<Self> {
278        Ok(true)
279    }
280
281    #[allow(clippy::wrong_self_convention)] // false positive
282    fn from_bool(value: bool) -> Result<Self> {
283        Ok(value)
284    }
285
286    fn from_string(value: &str) -> Result<Self> {
287        value.parse().map_err(|_| Error::unknown_value(value))
288    }
289}
290
291impl FromMeta for AtomicBool {
292    fn from_meta(mi: &Meta) -> Result<Self> {
293        FromMeta::from_meta(mi)
294            .map(AtomicBool::new)
295            .map_err(|e| e.with_span(mi))
296    }
297}
298
299impl FromMeta for char {
300    #[allow(clippy::wrong_self_convention)] // false positive
301    fn from_char(value: char) -> Result<Self> {
302        Ok(value)
303    }
304
305    fn from_string(s: &str) -> Result<Self> {
306        let mut chars = s.chars();
307        let char1 = chars.next();
308        let char2 = chars.next();
309
310        if let (Some(char), None) = (char1, char2) {
311            Ok(char)
312        } else {
313            Err(Error::unexpected_type("string"))
314        }
315    }
316}
317
318impl FromMeta for String {
319    fn from_string(s: &str) -> Result<Self> {
320        Ok(s.to_string())
321    }
322}
323
324impl FromMeta for std::path::PathBuf {
325    fn from_string(s: &str) -> Result<Self> {
326        Ok(s.into())
327    }
328}
329
330/// Generate an impl of `FromMeta` that will accept strings which parse to numbers or
331/// integer literals.
332macro_rules! from_meta_num {
333    ($ty:path) => {
334        impl FromMeta for $ty {
335            fn from_string(s: &str) -> Result<Self> {
336                s.parse().map_err(|_| Error::unknown_value(s))
337            }
338
339            fn from_value(value: &Lit) -> Result<Self> {
340                (match *value {
341                    Lit::Str(ref s) => Self::from_string(&s.value()),
342                    Lit::Int(ref s) => s.base10_parse::<$ty>().map_err(Error::from),
343                    _ => Err(Error::unexpected_lit_type(value)),
344                })
345                .map_err(|e| e.with_span(value))
346            }
347        }
348    };
349}
350
351from_meta_num!(u8);
352from_meta_num!(u16);
353from_meta_num!(u32);
354from_meta_num!(u64);
355from_meta_num!(u128);
356from_meta_num!(usize);
357from_meta_num!(i8);
358from_meta_num!(i16);
359from_meta_num!(i32);
360from_meta_num!(i64);
361from_meta_num!(i128);
362from_meta_num!(isize);
363from_meta_num!(num::NonZeroU8);
364from_meta_num!(num::NonZeroU16);
365from_meta_num!(num::NonZeroU32);
366from_meta_num!(num::NonZeroU64);
367from_meta_num!(num::NonZeroU128);
368from_meta_num!(num::NonZeroUsize);
369from_meta_num!(num::NonZeroI8);
370from_meta_num!(num::NonZeroI16);
371from_meta_num!(num::NonZeroI32);
372from_meta_num!(num::NonZeroI64);
373from_meta_num!(num::NonZeroI128);
374from_meta_num!(num::NonZeroIsize);
375
376/// Generate an impl of `FromMeta` that will accept strings which parse to floats or
377/// float literals.
378macro_rules! from_meta_float {
379    ($ty:ident) => {
380        impl FromMeta for $ty {
381            fn from_string(s: &str) -> Result<Self> {
382                s.parse().map_err(|_| Error::unknown_value(s))
383            }
384
385            fn from_value(value: &Lit) -> Result<Self> {
386                (match *value {
387                    Lit::Str(ref s) => Self::from_string(&s.value()),
388                    Lit::Float(ref s) => s.base10_parse::<$ty>().map_err(Error::from),
389                    _ => Err(Error::unexpected_lit_type(value)),
390                })
391                .map_err(|e| e.with_span(value))
392            }
393        }
394    };
395}
396
397from_meta_float!(f32);
398from_meta_float!(f64);
399
400/// Parsing support for punctuated. This attempts to preserve span information
401/// when available, but also supports parsing strings with the call site as the
402/// emitted span.
403impl<T: syn::parse::Parse, P: syn::parse::Parse> FromMeta for syn::punctuated::Punctuated<T, P> {
404    fn from_value(value: &Lit) -> Result<Self> {
405        if let Lit::Str(ref ident) = *value {
406            ident
407                .parse_with(syn::punctuated::Punctuated::parse_terminated)
408                .map_err(|_| Error::unknown_lit_str_value(ident))
409        } else {
410            Err(Error::unexpected_lit_type(value))
411        }
412    }
413}
414
415/// Support for arbitrary expressions as values in a meta item.
416///
417/// For backwards-compatibility to versions of `darling` based on `syn` 1,
418/// string literals will be "unwrapped" and their contents will be parsed
419/// as an expression.
420///
421/// See [`util::parse_expr`](crate::util::parse_expr) for functions to provide
422/// alternate parsing modes for this type.
423impl FromMeta for syn::Expr {
424    fn from_expr(expr: &Expr) -> Result<Self> {
425        match expr {
426            Expr::Lit(syn::ExprLit {
427                lit: lit @ syn::Lit::Str(_),
428                ..
429            }) => Self::from_value(lit),
430            Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
431            _ => Ok(expr.clone()),
432        }
433    }
434
435    fn from_string(value: &str) -> Result<Self> {
436        syn::parse_str(value).map_err(|_| Error::unknown_value(value))
437    }
438
439    fn from_value(value: &::syn::Lit) -> Result<Self> {
440        if let ::syn::Lit::Str(ref v) = *value {
441            v.parse::<syn::Expr>()
442                .map_err(|_| Error::unknown_lit_str_value(v))
443        } else {
444            Err(Error::unexpected_lit_type(value))
445        }
446    }
447}
448
449/// Parser for paths that supports both quote-wrapped and bare values.
450impl FromMeta for syn::Path {
451    fn from_string(value: &str) -> Result<Self> {
452        syn::parse_str(value).map_err(|_| Error::unknown_value(value))
453    }
454
455    fn from_value(value: &::syn::Lit) -> Result<Self> {
456        if let ::syn::Lit::Str(ref v) = *value {
457            v.parse().map_err(|_| Error::unknown_lit_str_value(v))
458        } else {
459            Err(Error::unexpected_lit_type(value))
460        }
461    }
462
463    fn from_expr(expr: &Expr) -> Result<Self> {
464        match expr {
465            Expr::Lit(lit) => Self::from_value(&lit.lit),
466            Expr::Path(path) => Ok(path.path.clone()),
467            Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
468            _ => Err(Error::unexpected_expr_type(expr)),
469        }
470    }
471}
472
473impl FromMeta for syn::Ident {
474    fn from_string(value: &str) -> Result<Self> {
475        syn::parse_str(value).map_err(|_| Error::unknown_value(value))
476    }
477
478    fn from_value(value: &syn::Lit) -> Result<Self> {
479        if let syn::Lit::Str(ref v) = *value {
480            v.parse().map_err(|_| Error::unknown_lit_str_value(v))
481        } else {
482            Err(Error::unexpected_lit_type(value))
483        }
484    }
485
486    fn from_expr(expr: &Expr) -> Result<Self> {
487        match expr {
488            Expr::Lit(lit) => Self::from_value(&lit.lit),
489            // All idents are paths, but not all paths are idents -
490            // the get_ident() method does additional validation to
491            // make sure the path is actually an ident.
492            Expr::Path(path) => match path.path.get_ident() {
493                Some(ident) => Ok(ident.clone()),
494                None => Err(Error::unexpected_expr_type(expr)),
495            },
496            Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
497            _ => Err(Error::unexpected_expr_type(expr)),
498        }
499    }
500}
501
502/// Adapter for various expression types.
503///
504/// Prior to syn 2.0, darling supported arbitrary expressions as long as they
505/// were wrapped in quotation marks. This was helpful for people writing
506/// libraries that needed expressions, but it now creates an ambiguity when
507/// parsing a meta item.
508///
509/// To address this, the macro supports both formats; if it cannot parse the
510/// item as an expression of the right type and the passed-in expression is
511/// a string literal, it will fall back to parsing the string contents.
512macro_rules! from_syn_expr_type {
513    ($ty:path, $variant:ident) => {
514        impl FromMeta for $ty {
515            fn from_expr(expr: &syn::Expr) -> Result<Self> {
516                match expr {
517                    syn::Expr::$variant(body) => Ok(body.clone()),
518                    syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit),
519                    syn::Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
520                    _ => Err(Error::unexpected_expr_type(expr)),
521                }
522            }
523
524            fn from_value(value: &::syn::Lit) -> Result<Self> {
525                if let syn::Lit::Str(body) = &value {
526                    body.parse::<$ty>()
527                        .map_err(|_| Error::unknown_lit_str_value(body))
528                } else {
529                    Err(Error::unexpected_lit_type(value))
530                }
531            }
532        }
533    };
534}
535
536from_syn_expr_type!(syn::ExprArray, Array);
537from_syn_expr_type!(syn::ExprPath, Path);
538from_syn_expr_type!(syn::ExprRange, Range);
539
540/// Adapter from `syn::parse::Parse` to `FromMeta` for items that cannot
541/// be expressed in a [`syn::MetaNameValue`].
542///
543/// This cannot be a blanket impl, due to the `syn::Lit` family's need to handle non-string values.
544/// Therefore, we use a macro and a lot of impls.
545macro_rules! from_syn_parse {
546    ($ty:path) => {
547        impl FromMeta for $ty {
548            fn from_string(value: &str) -> Result<Self> {
549                syn::parse_str(value).map_err(|_| Error::unknown_value(value))
550            }
551
552            fn from_value(value: &::syn::Lit) -> Result<Self> {
553                if let ::syn::Lit::Str(ref v) = *value {
554                    v.parse::<$ty>()
555                        .map_err(|_| Error::unknown_lit_str_value(v))
556                } else {
557                    Err(Error::unexpected_lit_type(value))
558                }
559            }
560
561            fn from_expr(expr: &Expr) -> Result<Self> {
562                match *expr {
563                    Expr::Lit(ref lit) => Self::from_value(&lit.lit),
564                    Expr::Group(ref group) => {
565                        // syn may generate this invisible group delimiter when the input to the darling
566                        // proc macro (specifically, the attributes) are generated by a
567                        // macro_rules! (e.g. propagating a macro_rules!'s expr)
568                        // Since we want to basically ignore these invisible group delimiters,
569                        // we just propagate the call to the inner expression.
570                        Self::from_expr(&group.expr)
571                    }
572                    // Parse valid expressions as this type T implementing Parse instead.
573                    // For example, `_` is both an expression and a type. Parse it as a type.
574                    _ => Ok(syn::parse2(expr.into_token_stream().clone())?),
575                }
576                .map_err(|e| e.with_span(expr))
577            }
578
579            fn from_invalid_expr(value: &MetaNameValueInvalidExpr) -> Result<Self> {
580                syn::parse2(value.value.clone()).map_err(Into::into)
581            }
582        }
583    };
584}
585
586from_syn_parse!(syn::Type);
587from_syn_parse!(syn::TypeArray);
588from_syn_parse!(syn::TypeFnPtr);
589from_syn_parse!(syn::TypeGroup);
590from_syn_parse!(syn::TypeImplTrait);
591from_syn_parse!(syn::TypeInfer);
592from_syn_parse!(syn::TypeMacro);
593from_syn_parse!(syn::TypeNever);
594from_syn_parse!(syn::TypeParam);
595from_syn_parse!(syn::TypeParen);
596from_syn_parse!(syn::TypePtr);
597from_syn_parse!(syn::TypeReference);
598from_syn_parse!(syn::TypeSlice);
599from_syn_parse!(syn::TypeTraitObject);
600from_syn_parse!(syn::TypeTuple);
601from_syn_parse!(syn::Visibility);
602from_syn_parse!(syn::WhereClause);
603
604impl FromMeta for syn::TypePath {
605    /// Supports both quote-wrapped and bare values.
606    fn from_expr(expr: &Expr) -> Result<Self> {
607        match expr {
608            Expr::Path(body) => {
609                if body.attrs.is_empty() {
610                    Ok(syn::TypePath {
611                        attrs: vec![],
612                        qself: body.qself.clone(),
613                        path: body.path.clone(),
614                    })
615                } else {
616                    Err(Error::custom("attributes are not allowed").with_span(body))
617                }
618            }
619            Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit),
620            Expr::Group(group) => Self::from_expr(&group.expr),
621            _ => Err(Error::unexpected_expr_type(expr)),
622        }
623    }
624
625    fn from_string(value: &str) -> Result<Self> {
626        syn::parse_str(value).map_err(|_| Error::unknown_value(value))
627    }
628
629    fn from_value(value: &Lit) -> Result<Self> {
630        if let Lit::Str(ref v) = *value {
631            v.parse().map_err(|_| Error::unknown_lit_str_value(v))
632        } else {
633            Err(Error::unexpected_lit_type(value))
634        }
635    }
636}
637
638macro_rules! from_numeric_array {
639    ($ty:ident) => {
640        /// Parsing an unsigned integer array, i.e. `example = "[1, 2, 3, 4]"`.
641        impl FromMeta for Vec<$ty> {
642            fn from_expr(expr: &syn::Expr) -> Result<Self> {
643                match expr {
644                    syn::Expr::Array(expr_array) => expr_array
645                        .elems
646                        .iter()
647                        .map(|expr| {
648                            let unexpected = || {
649                                Error::custom("Expected array of unsigned integers").with_span(expr)
650                            };
651                            match expr {
652                                Expr::Lit(lit) => $ty::from_value(&lit.lit),
653                                Expr::Group(group) => match &*group.expr {
654                                    Expr::Lit(lit) => $ty::from_value(&lit.lit),
655                                    _ => Err(unexpected()),
656                                },
657                                _ => Err(unexpected()),
658                            }
659                        })
660                        .collect::<Result<Vec<$ty>>>(),
661                    syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit),
662                    syn::Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr
663                    _ => Err(Error::unexpected_expr_type(expr)),
664                }
665            }
666
667            fn from_value(value: &Lit) -> Result<Self> {
668                let expr_array = syn::ExprArray::from_value(value)?;
669                Self::from_expr(&syn::Expr::Array(expr_array))
670            }
671        }
672    };
673}
674
675from_numeric_array!(u8);
676from_numeric_array!(u16);
677from_numeric_array!(u32);
678from_numeric_array!(u64);
679from_numeric_array!(usize);
680
681impl FromMeta for syn::Lit {
682    fn from_value(value: &Lit) -> Result<Self> {
683        Ok(value.clone())
684    }
685}
686
687macro_rules! from_meta_lit {
688    ($impl_ty:path, $lit_variant:path) => {
689        impl FromMeta for $impl_ty {
690            fn from_value(value: &Lit) -> Result<Self> {
691                if let $lit_variant(ref value) = *value {
692                    Ok(value.clone())
693                } else {
694                    Err(Error::unexpected_lit_type(value))
695                }
696            }
697        }
698
699        impl FromMeta for Vec<$impl_ty> {
700            fn from_list(items: &[NestedMeta]) -> Result<Self> {
701                items
702                    .iter()
703                    .map(<$impl_ty as FromMeta>::from_nested_meta)
704                    .collect()
705            }
706
707            fn from_value(value: &syn::Lit) -> Result<Self> {
708                let expr_array = syn::ExprArray::from_value(value)?;
709                Self::from_expr(&syn::Expr::Array(expr_array))
710            }
711
712            fn from_expr(expr: &syn::Expr) -> Result<Self> {
713                match expr {
714                    syn::Expr::Array(expr_array) => expr_array
715                        .elems
716                        .iter()
717                        .map(<$impl_ty as FromMeta>::from_expr)
718                        .collect::<Result<Vec<_>>>(),
719                    syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit),
720                    syn::Expr::Group(g) => Self::from_expr(&g.expr),
721                    _ => Err(Error::unexpected_expr_type(expr)),
722                }
723            }
724        }
725    };
726}
727
728from_meta_lit!(syn::LitInt, Lit::Int);
729from_meta_lit!(syn::LitFloat, Lit::Float);
730from_meta_lit!(syn::LitStr, Lit::Str);
731from_meta_lit!(syn::LitByte, Lit::Byte);
732from_meta_lit!(syn::LitByteStr, Lit::ByteStr);
733from_meta_lit!(syn::LitChar, Lit::Char);
734from_meta_lit!(syn::LitBool, Lit::Bool);
735from_meta_lit!(proc_macro2::Literal, Lit::Verbatim);
736
737impl FromMeta for syn::Meta {
738    fn from_meta(value: &syn::Meta) -> Result<Self> {
739        Ok(value.clone())
740    }
741}
742
743impl FromMeta for Vec<syn::WherePredicate> {
744    fn from_string(value: &str) -> Result<Self> {
745        syn::WhereClause::from_string(&format!("where {}", value))
746            .map(|c| c.predicates.into_iter().collect())
747    }
748
749    fn from_value(value: &Lit) -> Result<Self> {
750        if let syn::Lit::Str(s) = value {
751            syn::WhereClause::from_value(&syn::Lit::Str(syn::LitStr::new(
752                &format!("where {}", s.value()),
753                value.span(),
754            )))
755            .map(|c| c.predicates.into_iter().collect())
756        } else {
757            Err(Error::unexpected_lit_type(value))
758        }
759    }
760}
761
762impl FromMeta for ident_case::RenameRule {
763    fn from_string(value: &str) -> Result<Self> {
764        value.parse().map_err(|_| Error::unknown_value(value))
765    }
766}
767
768impl<T: FromMeta> FromMeta for Option<T> {
769    fn from_none() -> Option<Self> {
770        Some(None)
771    }
772
773    fn from_meta(item: &Meta) -> Result<Self> {
774        FromMeta::from_meta(item).map(Some)
775    }
776}
777
778impl<T: FromMeta> FromMeta for Result<T> {
779    fn from_none() -> Option<Self> {
780        T::from_none().map(Ok)
781    }
782
783    // `#[darling(flatten)]` forwards directly to this method, so it's
784    // necessary to declare it to avoid getting an unsupported format
785    // error if it's invoked directly.
786    fn from_list(items: &[NestedMeta]) -> Result<Self> {
787        Ok(FromMeta::from_list(items))
788    }
789
790    fn from_meta(item: &Meta) -> Result<Self> {
791        Ok(FromMeta::from_meta(item))
792    }
793}
794
795/// Create an impl that forwards to an inner type `T` for parsing.
796macro_rules! smart_pointer_t {
797    ($ty:path, $map_fn:path) => {
798        impl<T: FromMeta> FromMeta for $ty {
799            fn from_none() -> Option<Self> {
800                T::from_none().map($map_fn)
801            }
802
803            // `#[darling(flatten)]` forwards directly to this method, so it's
804            // necessary to declare it to avoid getting an unsupported format
805            // error if it's invoked directly.
806            fn from_list(items: &[NestedMeta]) -> Result<Self> {
807                FromMeta::from_list(items).map($map_fn)
808            }
809
810            fn from_meta(item: &Meta) -> Result<Self> {
811                FromMeta::from_meta(item).map($map_fn)
812            }
813        }
814    };
815}
816
817smart_pointer_t!(Box<T>, Box::new);
818smart_pointer_t!(Rc<T>, Rc::new);
819smart_pointer_t!(Arc<T>, Arc::new);
820smart_pointer_t!(RefCell<T>, RefCell::new);
821
822/// Parses the meta-item, and in case of error preserves a copy of the input for
823/// later analysis.
824impl<T: FromMeta> FromMeta for ::std::result::Result<T, Meta> {
825    fn from_meta(item: &Meta) -> Result<Self> {
826        T::from_meta(item)
827            .map(Ok)
828            .or_else(|_| Ok(Err(item.clone())))
829    }
830}
831
832/// Trait to convert from a path into an owned key for a map.
833trait KeyFromPath: Sized {
834    fn from_path(path: &syn::Path) -> Result<Self>;
835    fn to_display(&self) -> Cow<'_, str>;
836}
837
838impl KeyFromPath for String {
839    fn from_path(path: &syn::Path) -> Result<Self> {
840        Ok(path_to_string(path))
841    }
842
843    fn to_display(&self) -> Cow<'_, str> {
844        Cow::Borrowed(self)
845    }
846}
847
848impl KeyFromPath for syn::Path {
849    fn from_path(path: &syn::Path) -> Result<Self> {
850        Ok(path.clone())
851    }
852
853    fn to_display(&self) -> Cow<'_, str> {
854        Cow::Owned(path_to_string(self))
855    }
856}
857
858impl KeyFromPath for syn::Ident {
859    fn from_path(path: &syn::Path) -> Result<Self> {
860        if path.segments.len() == 1
861            && path.leading_colon.is_none()
862            && path.segments[0].arguments.is_empty()
863        {
864            Ok(path.segments[0].ident.clone())
865        } else {
866            Err(Error::custom("Key must be an identifier").with_span(path))
867        }
868    }
869
870    fn to_display(&self) -> Cow<'_, str> {
871        Cow::Owned(self.to_string())
872    }
873}
874
875macro_rules! map {
876    (hash_map, $key:ty, $nested:ident) => {
877        impl<V: FromMeta, S: BuildHasher + Default> FromMeta for HashMap<$key, V, S> {
878            map!(
879                HashMap::with_capacity_and_hasher($nested.len(), Default::default()),
880                $key,
881                $nested
882            );
883        }
884    };
885
886    (btree_map, $key:ty, $nested:ident) => {
887        impl<V: FromMeta> FromMeta for BTreeMap<$key, V> {
888            map!(BTreeMap::new(), $key, $nested);
889        }
890    };
891
892    ($new:expr, $key:ty, $nested:ident) => {
893        fn from_list($nested: &[NestedMeta]) -> Result<Self> {
894            // Convert the nested meta items into a sequence of (path, value result) result tuples.
895            // An outer Err means no (key, value) structured could be found, while an Err in the
896            // second position of the tuple means that value was rejected by FromMeta.
897            //
898            // We defer key conversion into $key so that we don't lose span information in the case
899            // of String keys; we'll need it for good duplicate key errors later.
900            let pairs = $nested
901                .iter()
902                .map(|item| -> Result<(&syn::Path, Result<V>)> {
903                    match *item {
904                        NestedMeta::Meta(ref inner) => {
905                            let path = inner.path();
906                            Ok((
907                                path,
908                                FromMeta::from_meta(inner).map_err(|e| e.at_path(&path)),
909                            ))
910                        }
911                        NestedMeta::NameValueInvalidExpr(ref inner) => Ok((
912                            &inner.path,
913                            FromMeta::from_invalid_expr(inner).map_err(|e| e.at_path(&inner.path)),
914                        )),
915                        NestedMeta::Lit(_) => Err(Error::unsupported_format("expression")),
916                    }
917                });
918
919            let mut errors = Error::accumulator();
920            // We need to track seen keys separately from the final map, since a seen key with an
921            // Err value won't go into the final map but should trigger a duplicate field error.
922            //
923            // This is a set of $key rather than Path to avoid the possibility that a key type
924            // parses two paths of different values to the same key value.
925            let mut seen_keys = HashSet::with_capacity($nested.len());
926
927            // The map to return in the Ok case. Its size will always be exactly nested.len(),
928            // since otherwise ≥1 field had a problem and the entire map is dropped immediately
929            // when the function returns `Err`.
930            let mut map = $new;
931
932            for item in pairs {
933                if let Some((path, value)) = errors.handle(item) {
934                    let key: $key = match KeyFromPath::from_path(path) {
935                        Ok(k) => k,
936                        Err(e) => {
937                            errors.push(e);
938
939                            // Surface value errors even under invalid keys
940                            errors.handle(value);
941
942                            continue;
943                        }
944                    };
945
946                    let already_seen = seen_keys.contains(&key);
947
948                    if already_seen {
949                        errors.push(Error::duplicate_field(&key.to_display()).with_span(path));
950                    }
951
952                    match value {
953                        Ok(_) if already_seen => {}
954                        Ok(val) => {
955                            map.insert(key.clone(), val);
956                        }
957                        Err(e) => {
958                            errors.push(e);
959                        }
960                    }
961
962                    seen_keys.insert(key);
963                }
964            }
965
966            errors.finish_with(map)
967        }
968    };
969}
970
971// This is done as a macro rather than a blanket impl to avoid breaking backwards compatibility
972// with 0.12.x, while still sharing the same impl.
973map!(hash_map, String, nested);
974map!(hash_map, syn::Ident, nested);
975map!(hash_map, syn::Path, nested);
976
977map!(btree_map, String, nested);
978map!(btree_map, syn::Ident, nested);
979
980#[doc(hidden)]
981/// Autoref specialization to allow using `.from_none()` on types `T` implementing
982/// `FromMeta` to get `Option<T>`,  and on other types always getting `None`
983///
984/// This is used inside the `#[derive(FromMeta)]` impl, see
985/// issue: <https://github.com/TedDriggs/darling/issues/305>
986///
987/// # How it works
988///
989/// When using method call syntax, if Rust can't find the method, then Rust will
990/// insert an extra reference `&` and try again.
991///
992/// This allows a form of "specialization", which can't be used in a generic context
993/// BUT it can be used with "concrete" types that are known at compile time.
994///
995/// This is only useful inside of macros.
996///
997/// This is known as "autoref specialization", more information can be found here:
998/// <https://github.com/dtolnay/case-studies/tree/master/autoref-specialization>
999///
1000/// # Usage
1001///
1002/// ```ignore
1003/// use _darling::autoref_specialization::{
1004///     SpecFromMeta as _,
1005///     SpecFromMetaAll as _
1006/// };
1007///
1008/// let x = (&_darling::export::PhantomData::<T>).tag().from_none()
1009/// ```
1010///
1011/// If `T` implements `FromMeta`, `x` will be `T::from_meta()` (an `Option<T>`)
1012/// because `(&PhantomData::<T>).tag()` selects the `SpecFromMeta` trait impl, and evaluates to `FromMetaTag`,
1013/// which then calls `FromMetaTag::<T>.from_none()` getting us the value of `T`.
1014///
1015/// Otherwise, if `T` does not implement `FromMeta`, `x` will always be `None` because
1016/// `(&PhantomData::<T>).tag()` selects the `SpecFromMetaAll` trait impl, and evaluates to `FromMetaTagAll`,
1017/// which then calls `FromMetaTagAll::<T>.from_none()` which always just returns `None`.
1018///
1019/// The `PhantomData` must be there because we must use exactly method call syntax, so the function
1020/// must take `self`, but we don't have an instantiation of `T`, we just have the type. Usually
1021/// auto-ref specialization works on concrete expressions.
1022#[allow(clippy::wrong_self_convention)]
1023pub mod autoref_specialization {
1024    use super::FromMeta;
1025    use std::marker::PhantomData;
1026
1027    pub struct FromMetaTag<T>(PhantomData<T>);
1028    pub struct FromMetaTagAll<T>(PhantomData<T>);
1029
1030    impl<T: FromMeta> FromMetaTag<T> {
1031        pub fn from_none(self) -> Option<T> {
1032            T::from_none()
1033        }
1034    }
1035
1036    impl<T> FromMetaTagAll<T> {
1037        pub fn from_none(self) -> Option<T> {
1038            None
1039        }
1040    }
1041
1042    pub trait SpecFromMeta<T>: Sized {
1043        fn tag(self) -> FromMetaTag<T> {
1044            FromMetaTag(PhantomData)
1045        }
1046    }
1047
1048    pub trait SpecFromMetaAll<T>: Sized {
1049        fn tag(self) -> FromMetaTagAll<T> {
1050            FromMetaTagAll(PhantomData)
1051        }
1052    }
1053
1054    // Less specific than the next impl, so this will get
1055    // selected if the next impl isn't because Rust will add a `&`
1056    // and try again
1057    impl<T> SpecFromMetaAll<T> for &&PhantomData<T> {}
1058
1059    impl<T: FromMeta> SpecFromMeta<T> for &PhantomData<T> {}
1060}
1061
1062impl FromMeta for Vec<Ident> {
1063    fn from_list(nested: &[NestedMeta]) -> Result<Self> {
1064        let items = nested.iter().map(|item| match *item {
1065            NestedMeta::Meta(ref inner) => Ok(inner.require_path_only()?.require_ident()?),
1066            NestedMeta::NameValueInvalidExpr(_) | NestedMeta::Lit(_) => {
1067                Err(Error::unsupported_format("expression"))
1068            }
1069        });
1070
1071        let mut errors = Error::accumulator();
1072
1073        let list = items
1074            .filter_map(|item| errors.handle(item))
1075            .cloned()
1076            .collect();
1077
1078        errors.finish_with(list)
1079    }
1080}
1081
1082impl FromMeta for Vec<Path> {
1083    fn from_list(nested: &[NestedMeta]) -> Result<Self> {
1084        let items = nested.iter().map(|item| match *item {
1085            NestedMeta::Meta(ref inner) => Ok(inner.require_path_only()?),
1086            NestedMeta::NameValueInvalidExpr(_) | NestedMeta::Lit(_) => {
1087                Err(Error::unsupported_format("expression"))
1088            }
1089        });
1090
1091        let mut errors = Error::accumulator();
1092
1093        let list = items
1094            .filter_map(|item| errors.handle(item))
1095            .cloned()
1096            .collect();
1097
1098        errors.finish_with(list)
1099    }
1100}
1101
1102impl FromMeta for HashSet<Ident> {
1103    fn from_list(nested: &[NestedMeta]) -> Result<Self> {
1104        let items = nested.iter().map(|item| match *item {
1105            NestedMeta::Meta(ref inner) => Ok(inner.require_path_only()?.require_ident()?),
1106            NestedMeta::NameValueInvalidExpr(_) | NestedMeta::Lit(_) => {
1107                Err(Error::unsupported_format("expression"))
1108            }
1109        });
1110
1111        let mut errors = Error::accumulator();
1112        let mut list = HashSet::with_capacity(nested.len());
1113
1114        for item in items {
1115            let Some(item) = errors.handle(item) else {
1116                continue;
1117            };
1118            if !list.insert(item.clone()) {
1119                errors.push(Error::duplicate_field(&item.to_string()).with_span(item))
1120            };
1121        }
1122
1123        errors.finish_with(list)
1124    }
1125}
1126
1127impl FromMeta for HashSet<Path> {
1128    fn from_list(nested: &[NestedMeta]) -> Result<Self> {
1129        let items = nested.iter().map(|item| match *item {
1130            NestedMeta::Meta(ref inner) => Ok(inner.require_path_only()?),
1131            NestedMeta::NameValueInvalidExpr(_) | NestedMeta::Lit(_) => {
1132                Err(Error::unsupported_format("expression"))
1133            }
1134        });
1135
1136        let mut errors = Error::accumulator();
1137        let mut list = HashSet::with_capacity(nested.len());
1138
1139        for item in items {
1140            let Some(item) = errors.handle(item) else {
1141                continue;
1142            };
1143            if !list.insert(item.clone()) {
1144                errors.push(Error::duplicate_field(&path_to_string(item)).with_span(item))
1145            };
1146        }
1147
1148        errors.finish_with(list)
1149    }
1150}
1151
1152/// Tests for `FromMeta` implementations. Wherever the word `ignore` appears in test input,
1153/// it should not be considered by the parsing.
1154#[cfg(test)]
1155mod tests {
1156    use std::{
1157        collections::HashSet,
1158        fmt::Debug,
1159        num::{NonZeroU32, NonZeroU64},
1160    };
1161
1162    use proc_macro2::TokenStream;
1163    use quote::quote;
1164    use syn::{
1165        parse_quote, Ident, Path, Type, TypeArray, TypeFnPtr, TypeImplTrait, TypeInfer, TypeNever,
1166        TypeParen, TypePtr, TypeReference, TypeSlice, TypeTraitObject, TypeTuple, Visibility,
1167        WhereClause,
1168    };
1169
1170    use crate::{Error, FromMeta, Result};
1171
1172    #[track_caller]
1173    fn test_type<T: FromMeta + PartialEq + Debug>(tokens: TokenStream, f: fn(T) -> Type) {
1174        // Should work if the type is in a string literal
1175        let tokens_str = tokens.to_string();
1176        let t1 = pnm::<T>(tokens.clone()).expect("1");
1177        let t2 = pnm::<T>(quote! { #tokens_str }).expect("2");
1178        let type1 = pnm::<Type>(tokens).expect("3");
1179        let type2 = pnm::<Type>(quote! { #tokens_str }).expect("4");
1180
1181        assert_eq!(t1, t2, "5");
1182        assert_eq!(type1, type2, "6");
1183        assert_eq!(f(t1), type1, "7");
1184        assert_eq!(f(t2), type1, "8");
1185    }
1186
1187    /// parse a string as a syn::Meta instance.
1188    fn pm(tokens: TokenStream) -> ::std::result::Result<syn::Meta, String> {
1189        let attribute: syn::Attribute = parse_quote!(#[#tokens]);
1190        Ok(attribute.meta)
1191    }
1192
1193    /// assert that this value parses into NestedMeta
1194    #[track_caller]
1195    fn pnm<T: FromMeta>(ts: TokenStream) -> Result<T> {
1196        T::from_nested_meta(&parse_quote!(ignore = #ts))
1197    }
1198
1199    #[track_caller]
1200    fn fm<T: FromMeta>(tokens: TokenStream) -> T {
1201        FromMeta::from_meta(&pm(tokens).expect("Tests should pass well-formed input"))
1202            .expect("Tests should pass valid input")
1203    }
1204
1205    #[test]
1206    fn unit_succeeds() {
1207        fm::<()>(quote!(ignore));
1208        fm::<()>(quote!(ignore()));
1209    }
1210
1211    #[test]
1212    #[should_panic(expected = "UnknownField")]
1213    fn unit_fails() {
1214        fm::<()>(quote!(ignore(foo = "bar")));
1215    }
1216
1217    #[test]
1218    #[allow(clippy::bool_assert_comparison)]
1219    fn bool_succeeds() {
1220        // word format
1221        assert_eq!(fm::<bool>(quote!(ignore)), true);
1222
1223        // bool literal
1224        assert_eq!(fm::<bool>(quote!(ignore = true)), true);
1225        assert_eq!(fm::<bool>(quote!(ignore = false)), false);
1226
1227        // string literals
1228        assert_eq!(fm::<bool>(quote!(ignore = "true")), true);
1229        assert_eq!(fm::<bool>(quote!(ignore = "false")), false);
1230    }
1231
1232    #[test]
1233    fn char_succeeds() {
1234        // char literal
1235        assert_eq!(fm::<char>(quote!(ignore = '😬')), '😬');
1236
1237        // string literal
1238        assert_eq!(fm::<char>(quote!(ignore = "😬")), '😬');
1239    }
1240
1241    #[test]
1242    fn string_succeeds() {
1243        // cooked form
1244        assert_eq!(&fm::<String>(quote!(ignore = "world")), "world");
1245
1246        // raw form
1247        assert_eq!(&fm::<String>(quote!(ignore = r#"world"#)), "world");
1248    }
1249
1250    #[test]
1251    fn pathbuf_succeeds() {
1252        assert_eq!(
1253            fm::<std::path::PathBuf>(quote!(ignore = r#"C:\"#)),
1254            std::path::PathBuf::from(r#"C:\"#)
1255        );
1256    }
1257
1258    #[test]
1259    #[allow(clippy::float_cmp)] // we want exact equality
1260    fn number_succeeds() {
1261        assert_eq!(fm::<u8>(quote!(ignore = "2")), 2u8);
1262        assert_eq!(fm::<i16>(quote!(ignore = "-25")), -25i16);
1263        assert_eq!(fm::<f64>(quote!(ignore = "1.4e10")), 1.4e10);
1264    }
1265
1266    #[should_panic(expected = "UnknownValue")]
1267    #[test]
1268    fn nonzero_number_fails() {
1269        fm::<NonZeroU64>(quote!(ignore = "0"));
1270    }
1271
1272    #[test]
1273    fn nonzero_number_succeeds() {
1274        assert_eq!(
1275            fm::<NonZeroU32>(quote!(ignore = "2")),
1276            NonZeroU32::new(2).unwrap()
1277        );
1278    }
1279
1280    #[test]
1281    fn int_without_quotes() {
1282        assert_eq!(fm::<u8>(quote!(ignore = 2)), 2u8);
1283        assert_eq!(fm::<u16>(quote!(ignore = 255)), 255u16);
1284        assert_eq!(fm::<u32>(quote!(ignore = 5000)), 5000u32);
1285
1286        // Check that we aren't tripped up by incorrect suffixes
1287        assert_eq!(fm::<u32>(quote!(ignore = 5000i32)), 5000u32);
1288    }
1289
1290    #[test]
1291    fn negative_int_without_quotes() {
1292        assert_eq!(fm::<i8>(quote!(ignore = -2)), -2i8);
1293        assert_eq!(fm::<i32>(quote!(ignore = -255)), -255i32);
1294    }
1295
1296    #[test]
1297    #[allow(clippy::float_cmp)] // we want exact equality
1298    fn float_without_quotes() {
1299        assert_eq!(fm::<f32>(quote!(ignore = 2.)), 2.0f32);
1300        assert_eq!(fm::<f32>(quote!(ignore = 2.0)), 2.0f32);
1301        assert_eq!(fm::<f64>(quote!(ignore = 1.4e10)), 1.4e10f64);
1302    }
1303
1304    #[test]
1305    fn too_large_int_produces_error() {
1306        assert!(fm::<Result<u8>>(quote!(ignore = 2000)).is_err());
1307    }
1308
1309    #[test]
1310    fn meta_succeeds() {
1311        use syn::Meta;
1312
1313        assert_eq!(
1314            fm::<Meta>(quote!(hello(world, today))),
1315            pm(quote!(hello(world, today))).unwrap()
1316        );
1317    }
1318
1319    #[test]
1320    fn hash_map_succeeds() {
1321        use std::collections::HashMap;
1322
1323        let comparison = {
1324            let mut c = HashMap::new();
1325            c.insert("hello".to_string(), true);
1326            c.insert("world".to_string(), false);
1327            c.insert("there".to_string(), true);
1328            c
1329        };
1330
1331        assert_eq!(
1332            fm::<HashMap<String, bool>>(quote!(ignore(hello, world = false, there = "true"))),
1333            comparison
1334        );
1335    }
1336
1337    /// Check that a `HashMap` cannot have duplicate keys, and that the generated error
1338    /// is assigned a span to correctly target the diagnostic message.
1339    #[test]
1340    fn hash_map_duplicate() {
1341        use std::collections::HashMap;
1342
1343        let err: Result<HashMap<String, bool>> =
1344            FromMeta::from_meta(&pm(quote!(ignore(hello, hello = false))).unwrap());
1345
1346        let err = err.expect_err("Duplicate keys in HashMap should error");
1347
1348        assert!(err.has_span());
1349        assert_eq!(err.to_string(), Error::duplicate_field("hello").to_string());
1350    }
1351
1352    #[test]
1353    fn hash_map_multiple_errors() {
1354        use std::collections::HashMap;
1355
1356        let err = HashMap::<String, bool>::from_meta(
1357            &pm(quote!(ignore(hello, hello = 3, hello = false))).unwrap(),
1358        )
1359        .expect_err("Duplicates and bad values should error");
1360
1361        assert_eq!(err.len(), 3);
1362        let errors = err.into_iter().collect::<Vec<_>>();
1363        assert!(errors[0].has_span());
1364        assert!(errors[1].has_span());
1365        assert!(errors[2].has_span());
1366    }
1367
1368    #[test]
1369    fn hash_map_ident_succeeds() {
1370        use std::collections::HashMap;
1371        use syn::parse_quote;
1372
1373        let comparison = {
1374            let mut c = HashMap::<syn::Ident, bool>::new();
1375            c.insert(parse_quote!(first), true);
1376            c.insert(parse_quote!(second), false);
1377            c
1378        };
1379
1380        assert_eq!(
1381            fm::<HashMap<syn::Ident, bool>>(quote!(ignore(first, second = false))),
1382            comparison
1383        );
1384    }
1385
1386    #[test]
1387    fn hash_map_ident_rejects_non_idents() {
1388        use std::collections::HashMap;
1389
1390        let err: Result<HashMap<syn::Ident, bool>> =
1391            FromMeta::from_meta(&pm(quote!(ignore(first, the::second))).unwrap());
1392
1393        err.unwrap_err();
1394    }
1395
1396    #[test]
1397    fn hash_map_path_succeeds() {
1398        use std::collections::HashMap;
1399        use syn::parse_quote;
1400
1401        let comparison = {
1402            let mut c = HashMap::<syn::Path, bool>::new();
1403            c.insert(parse_quote!(first), true);
1404            c.insert(parse_quote!(the::second), false);
1405            c
1406        };
1407
1408        assert_eq!(
1409            fm::<HashMap<syn::Path, bool>>(quote!(ignore(first, the::second = false))),
1410            comparison
1411        );
1412    }
1413
1414    #[test]
1415    fn btree_map_succeeds() {
1416        use std::collections::BTreeMap;
1417
1418        let comparison = {
1419            let mut c = BTreeMap::new();
1420            c.insert("hello".to_string(), true);
1421            c.insert("world".to_string(), false);
1422            c.insert("there".to_string(), true);
1423            c
1424        };
1425
1426        assert_eq!(
1427            fm::<BTreeMap<String, bool>>(quote!(ignore(hello, world = false, there = "true"))),
1428            comparison
1429        );
1430    }
1431
1432    /// Check that a `HashMap` cannot have duplicate keys, and that the generated error
1433    /// is assigned a span to correctly target the diagnostic message.
1434    #[test]
1435    fn btree_map_duplicate() {
1436        use std::collections::BTreeMap;
1437
1438        let err: Result<BTreeMap<String, bool>> =
1439            FromMeta::from_meta(&pm(quote!(ignore(hello, hello = false))).unwrap());
1440
1441        let err = err.expect_err("Duplicate keys in BTreeMap should error");
1442
1443        assert!(err.has_span());
1444        assert_eq!(err.to_string(), Error::duplicate_field("hello").to_string());
1445    }
1446
1447    #[test]
1448    fn btree_map_multiple_errors() {
1449        use std::collections::BTreeMap;
1450
1451        let err = BTreeMap::<String, bool>::from_meta(
1452            &pm(quote!(ignore(hello, hello = 3, hello = false))).unwrap(),
1453        )
1454        .expect_err("Duplicates and bad values should error");
1455
1456        assert_eq!(err.len(), 3);
1457        let errors = err.into_iter().collect::<Vec<_>>();
1458        assert!(errors[0].has_span());
1459        assert!(errors[1].has_span());
1460        assert!(errors[2].has_span());
1461    }
1462
1463    #[test]
1464    fn btree_map_ident_succeeds() {
1465        use std::collections::BTreeMap;
1466        use syn::parse_quote;
1467
1468        let comparison = {
1469            let mut c = BTreeMap::<syn::Ident, bool>::new();
1470            c.insert(parse_quote!(first), true);
1471            c.insert(parse_quote!(second), false);
1472            c
1473        };
1474
1475        assert_eq!(
1476            fm::<BTreeMap<syn::Ident, bool>>(quote!(ignore(first, second = false))),
1477            comparison
1478        );
1479    }
1480
1481    #[test]
1482    fn btree_map_ident_rejects_non_idents() {
1483        use std::collections::BTreeMap;
1484
1485        let err: Result<BTreeMap<syn::Ident, bool>> =
1486            FromMeta::from_meta(&pm(quote!(ignore(first, the::second))).unwrap());
1487
1488        err.unwrap_err();
1489    }
1490
1491    #[test]
1492    fn btree_map_expr_values_succeed() {
1493        use std::collections::BTreeMap;
1494        use syn::parse_quote;
1495
1496        let comparison: BTreeMap<String, syn::Expr> = vec![
1497            ("hello", parse_quote!(2 + 2)),
1498            ("world", parse_quote!(x.foo())),
1499        ]
1500        .into_iter()
1501        .map(|(k, v)| (k.to_string(), v))
1502        .collect();
1503
1504        assert_eq!(
1505            fm::<BTreeMap<String, syn::Expr>>(quote!(ignore(hello = 2 + 2, world = x.foo()))),
1506            comparison
1507        );
1508    }
1509
1510    #[test]
1511    fn vec_ident_succeeds() {
1512        let input: Vec<Ident> = vec![
1513            parse_quote!(hello),
1514            parse_quote!(world),
1515            parse_quote!(there),
1516        ];
1517
1518        assert_eq!(fm::<Vec<Ident>>(quote!(ignore(hello, world, there))), input);
1519    }
1520
1521    #[test]
1522    fn vec_ident_allows_duplicates() {
1523        let input: Vec<Ident> = vec![parse_quote!(hello), parse_quote!(hello)];
1524
1525        assert_eq!(fm::<Vec<Ident>>(quote!(ignore(hello, hello))), input);
1526    }
1527
1528    #[test]
1529    fn vec_ident_rejects_paths() {
1530        let result: Result<Vec<Ident>> =
1531            FromMeta::from_meta(&pm(quote!(ignore(the::world))).unwrap());
1532
1533        result.unwrap_err();
1534    }
1535
1536    #[test]
1537    fn vec_path_succeeds() {
1538        let input = vec![parse_quote!(hello), parse_quote!(the::world)];
1539
1540        assert_eq!(
1541            fm::<Vec<syn::Path>>(quote!(ignore(hello, the::world))),
1542            input
1543        );
1544    }
1545
1546    #[test]
1547    fn vec_path_allows_duplicates() {
1548        let input = vec![parse_quote!(hello), parse_quote!(hello)];
1549
1550        assert_eq!(fm::<Vec<Path>>(quote!(ignore(hello, hello))), input);
1551    }
1552
1553    #[test]
1554    fn hash_set_ident_succeeds() {
1555        let comparison: HashSet<Ident> = [parse_quote!(hello), parse_quote!(world)].into();
1556
1557        assert_eq!(
1558            fm::<HashSet<Ident>>(quote!(ignore(hello, world))),
1559            comparison
1560        );
1561    }
1562
1563    #[test]
1564    fn hash_set_ident_duplicate() {
1565        HashSet::<syn::Ident>::from_meta(&pm(quote!(ignore(hello, hello))).unwrap()).unwrap_err();
1566    }
1567
1568    #[test]
1569    fn hash_set_ident_multiple_errors() {
1570        let err = HashSet::<syn::Ident>::from_meta(
1571            &pm(quote!(ignore(hello, hello, the::world))).unwrap(),
1572        )
1573        .unwrap_err();
1574
1575        assert_eq!(err.len(), 2);
1576    }
1577
1578    #[test]
1579    fn hash_set_path_succeeds() {
1580        let comparison: HashSet<_> = [parse_quote!(hello), parse_quote!(the::world)].into();
1581
1582        assert_eq!(
1583            fm::<HashSet<syn::Path>>(quote!(ignore(hello, the::world))),
1584            comparison
1585        );
1586    }
1587
1588    #[test]
1589    fn hash_set_path_duplicate() {
1590        HashSet::<syn::Path>::from_meta(&pm(quote!(ignore(the::world, the::world))).unwrap())
1591            .unwrap_err();
1592    }
1593
1594    /// Tests that fallible parsing will always produce an outer `Ok` (from `fm`),
1595    /// and will accurately preserve the inner contents.
1596    #[test]
1597    fn darling_result_succeeds() {
1598        fm::<Result<()>>(quote!(ignore)).unwrap();
1599        fm::<Result<()>>(quote!(ignore(world))).unwrap_err();
1600    }
1601
1602    /// Test punctuated
1603    #[test]
1604    fn test_punctuated() {
1605        fm::<syn::punctuated::Punctuated<syn::FnArg, syn::token::Comma>>(quote!(
1606            ignore = "a: u8, b: Type"
1607        ));
1608        fm::<syn::punctuated::Punctuated<syn::Expr, syn::token::Comma>>(quote!(ignore = "a, b, c"));
1609    }
1610
1611    #[test]
1612    fn test_expr_array() {
1613        fm::<syn::ExprArray>(quote!(ignore = "[0x1, 0x2]"));
1614        fm::<syn::ExprArray>(quote!(ignore = "[\"Hello World\", \"Test Array\"]"));
1615    }
1616
1617    #[test]
1618    fn test_expr() {
1619        fm::<syn::Expr>(quote!(ignore = "x + y"));
1620        fm::<syn::Expr>(quote!(ignore = "an_object.method_call()"));
1621        fm::<syn::Expr>(quote!(ignore = "{ a_statement(); in_a_block }"));
1622    }
1623
1624    #[test]
1625    fn test_expr_without_quotes() {
1626        fm::<syn::Expr>(quote!(ignore = x + y));
1627        fm::<syn::Expr>(quote!(ignore = an_object.method_call()));
1628        fm::<syn::Expr>(quote!(
1629            ignore = {
1630                a_statement();
1631                in_a_block
1632            }
1633        ));
1634    }
1635
1636    #[test]
1637    fn test_expr_path() {
1638        fm::<syn::ExprPath>(quote!(ignore = "std::mem::replace"));
1639        fm::<syn::ExprPath>(quote!(ignore = "x"));
1640        fm::<syn::ExprPath>(quote!(ignore = "example::<Test>"));
1641    }
1642
1643    #[test]
1644    fn test_expr_path_without_quotes() {
1645        fm::<syn::ExprPath>(quote!(ignore = std::mem::replace));
1646        fm::<syn::ExprPath>(quote!(ignore = x));
1647        fm::<syn::ExprPath>(quote!(ignore = example::<Test>));
1648    }
1649
1650    #[test]
1651    fn test_path_without_quotes() {
1652        fm::<syn::Path>(quote!(ignore = std::mem::replace));
1653        fm::<syn::Path>(quote!(ignore = x));
1654        fm::<syn::Path>(quote!(ignore = example::<Test>));
1655    }
1656
1657    #[test]
1658    fn test_number_array() {
1659        assert_eq!(fm::<Vec<u8>>(quote!(ignore = [16, 0xff])), vec![0x10, 0xff]);
1660        assert_eq!(
1661            fm::<Vec<u16>>(quote!(ignore = "[32, 0xffff]")),
1662            vec![0x20, 0xffff]
1663        );
1664        assert_eq!(
1665            fm::<Vec<u32>>(quote!(ignore = "[48, 0xffffffff]")),
1666            vec![0x30, 0xffffffff]
1667        );
1668        assert_eq!(
1669            fm::<Vec<u64>>(quote!(ignore = "[64, 0xffffffffffffffff]")),
1670            vec![0x40, 0xffffffffffffffff]
1671        );
1672        assert_eq!(
1673            fm::<Vec<usize>>(quote!(ignore = "[80, 0xffffffff]")),
1674            vec![0x50, 0xffffffff]
1675        );
1676    }
1677
1678    #[test]
1679    fn test_lit_array() {
1680        fm::<Vec<syn::LitStr>>(quote!(ignore = "[\"Hello World\", \"Test Array\"]"));
1681        fm::<Vec<syn::LitStr>>(quote!(ignore = ["Hello World", "Test Array"]));
1682        fm::<Vec<syn::LitChar>>(quote!(ignore = "['a', 'b', 'c']"));
1683        fm::<Vec<syn::LitBool>>(quote!(ignore = "[true]"));
1684        fm::<Vec<syn::LitStr>>(quote!(ignore = "[]"));
1685        fm::<Vec<syn::LitStr>>(quote!(ignore = []));
1686        fm::<Vec<syn::LitBool>>(quote!(ignore = [true, false]));
1687    }
1688
1689    #[test]
1690    fn expr_range_without_quotes() {
1691        fm::<syn::ExprRange>(quote!(ignore = 0..5));
1692        fm::<syn::ExprRange>(quote!(ignore = 0..=5));
1693        fm::<syn::ExprRange>(quote!(ignore = ..5));
1694        fm::<syn::ExprRange>(quote!(ignore = ..(x + y)));
1695    }
1696
1697    #[test]
1698    fn test_where_clause() {
1699        pnm::<WhereClause>(quote!(where T: Deserialize<'de>)).unwrap();
1700        // Must use quotes because this contains a comma. Due to this comma,
1701        // it thinks that the next value (D: 'static) is a NestedMeta
1702        pnm::<WhereClause>(quote!("where T: Deserialize<'de>, D: 'static")).unwrap();
1703    }
1704
1705    #[test]
1706    fn test_vis() {
1707        pnm::<Visibility>(quote!(pub(in crate::module))).unwrap();
1708        pnm::<Visibility>(quote!(pub)).unwrap();
1709    }
1710
1711    #[test]
1712    fn test_type_array() {
1713        test_type::<TypeArray>(quote!([u32; 4]), Type::Array);
1714    }
1715
1716    #[test]
1717    fn test_type_infer() {
1718        test_type::<TypeInfer>(quote!(_), Type::Infer);
1719    }
1720
1721    #[test]
1722    fn test_type_slice() {
1723        test_type::<TypeSlice>(quote!([u32]), Type::Slice);
1724    }
1725
1726    #[test]
1727    fn test_type_ptr() {
1728        test_type::<TypePtr>(quote!(*const T), Type::Ptr);
1729        test_type::<TypePtr>(quote!(*mut T), Type::Ptr);
1730    }
1731
1732    #[test]
1733    fn test_type_trait_object() {
1734        test_type::<TypeTraitObject>(quote!(dyn Trait), Type::TraitObject);
1735    }
1736
1737    #[test]
1738    fn test_type_never() {
1739        test_type::<TypeNever>(quote!(!), Type::Never);
1740    }
1741
1742    #[test]
1743    fn test_type_impl_trait() {
1744        test_type::<TypeImplTrait>(quote!(impl Trait + 'a), Type::ImplTrait);
1745    }
1746
1747    #[test]
1748    fn test_type_tuple() {
1749        test_type::<TypeTuple>(quote!((u32, i32)), Type::Tuple);
1750    }
1751
1752    #[test]
1753    fn test_type_reference() {
1754        test_type::<TypeReference>(quote!(&u32), Type::Reference);
1755        test_type::<TypeReference>(quote!(&'a mut u32), Type::Reference);
1756    }
1757
1758    #[test]
1759    fn test_type_bare_fn() {
1760        test_type::<TypeFnPtr>(quote!(fn(usize) -> bool), Type::FnPtr);
1761    }
1762
1763    #[test]
1764    fn test_type_paren() {
1765        test_type::<TypeParen>(quote!((u32)), Type::Paren);
1766    }
1767}