deluxe/
lib.rs

1//! # Deluxe
2//!
3//! A procedural macro attribute parser.
4//!
5//! ### Abstract
6//!
7//! This crate offers attribute parsing closer to the design of attributes in C#. It has an
8//! interface similar to [serde](https://serde.rs). Attributes are written as plain Rust structs or
9//! enums, and then parsers for them are generated automatically. They can contain arbitrary
10//! expressions and can inherit from other attributes using a flattening mechanism.
11//!
12//! The parsers in this crate directly parse token streams using [`syn`]. As a result, most
13//! built-in Rust types and `syn` types can be used directly as fields.
14//!
15//! ### Usage
16//!
17//! Functionality in this crate is centered around three traits, and their respective derive macros:
18//! - **[`ExtractAttributes`](macro@ExtractAttributes)**
19//!
20//!   Extracts attributes from an object containing a list of [`syn::Attribute`], and parses them
21//!   into a Rust type. Should be implemented for top-level structures that will be parsed directly
22//!   out of a set of matching attributes.
23//! - **[`ParseAttributes`](macro@ParseAttributes)**
24//!
25//!   Parses a Rust type from any object containing a list of [`syn::Attribute`]. Should be used if
26//!   the set of matching attributes can potentially be shared between this type and other types.
27//! - **[`ParseMetaItem`](macro@ParseMetaItem)**
28//!
29//!   Parses a Rust type from a [`ParseStream`](syn::parse::ParseStream). Should be implemented for
30//!   any types that can be nested inside an attribute.
31//!
32//! Basic usage of this crate in derive macros requires simply deriving one (or a few) of these
33//! traits, and then calling [`extract_attributes`] or [`parse_attributes`]. For more advanced
34//! functionality, several `#[deluxe(...)]` attributes are supported on structs, enums, variants
35//! and fields. See the examples below, and the documentation for each derive macro for a complete
36//! description of the supported attributes.
37//!
38//! A list of field types supported by default can be seen in the list of provided [`ParseMetaItem`
39//! implementations](trait@ParseMetaItem#foreign-impls). For more complex usage, manual
40//! implementations of these traits can be provided. See the documentation on individual traits in
41//! [`deluxe_core`] for more details on how to manually implement your own parsers.
42//!
43//! ### Related Crates
44//!
45//! Deluxe takes inspiration from the [darling](https://docs.rs/darling) crate, but offers a few
46//! enhancements over it. Darling is built around pre-parsed [`syn::Meta`] objects, and therefore
47//! is restricted to the [meta
48//! syntax](https://doc.rust-lang.org/stable/reference/attributes.html#meta-item-attribute-syntax).
49//! Deluxe parses its types directly from [`TokenStream`](proc_macro2::TokenStream) objects in the
50//! attributes and so is able to use any syntax that parses as a valid token tree. Deluxe also does
51//! not provide extra traits for parsing special `syn` objects like
52//! [`DeriveInput`](syn::DeriveInput) and [`Field`](syn::Field). Instead, Deluxe uses a generic
53//! trait to parse from any type containing a <code>[Vec]&lt;[syn::Attribute]></code>.
54//!
55//! ### Examples
56//!
57//! #### Basic Derive Macro
58//!
59//! To create a derive macro that can add some simple metadata to a Rust type from an attribute,
60//! start by defining a struct that derives [`ExtractAttributes`](macro@ExtractAttributes). Then,
61//! call [`extract_attributes`] in your derive macro to create an instance of the struct:
62//!
63//! ```
64//! #[derive(deluxe::ExtractAttributes)]
65//! #[deluxe(attributes(my_desc))]
66//! struct MyDescription {
67//!     name: String,
68//!     version: String,
69//! }
70//!
71//! fn my_derive(item: proc_macro2::TokenStream) -> deluxe::Result<proc_macro2::TokenStream> {
72//!     let mut input = syn::parse2::<syn::DeriveInput>(item)?;
73//!
74//!     // Extract the attributes!
75//!     let MyDescription { name, version } = deluxe::extract_attributes(&mut input)?;
76//!
77//!     // Now get some info to generate an associated function...
78//!     let ident = &input.ident;
79//!     let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
80//!
81//!     Ok(quote::quote! {
82//!         impl #impl_generics #ident #type_generics #where_clause {
83//!             fn my_desc() -> &'static str {
84//!                 concat!("Name: ", #name, ", Version: ", #version)
85//!             }
86//!         }
87//!     })
88//! }
89//!
90//! # let tokens = my_derive(quote::quote! {
91//! #     #[my_desc(name = "hello world", version = "0.2")]
92//! #     struct Hello;
93//! # }).unwrap();
94//! # let i: syn::ItemImpl = syn::parse_quote! { #tokens };
95//! # assert_eq!(i, syn::parse_quote! {
96//! #     impl Hello {
97//! #         fn my_desc() -> &'static str {
98//! #             concat!("Name: ", "hello world", ", Version: ", "0.2")
99//! #         }
100//! #     }
101//! # });
102//! ```
103//!
104//! Then, try adding the attribute in some code that uses your macro:
105//!
106//! ```ignore
107//! // In your macros crate
108//!
109//! #[proc_macro_derive(MyDescription, attributes(my_desc))]
110//! pub fn derive_my_description(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
111//!     my_derive(item.into()).unwrap().into()
112//! }
113//! ```
114//!
115//! ```ignore
116//! // In your normal code
117//!
118//! #[derive(MyDescription, Default)]
119//! #[my_desc(name = "hello world", version = "0.2")]
120//! struct Hello {
121//!     a: i32,
122//!     b: String
123//! }
124//!
125//! let hello: Hello = Default::default();
126//! assert_eq!(hello.my_desc(), "Name: hello world, Version: 0.2");
127//! ```
128//!
129//! #### Basic Attribute Macro
130//!
131//! The `parse` and `parse2` functions included in this crate can also be used as simple helpers
132//! for attribute macros:
133//!
134//! ```
135//! #[derive(deluxe::ParseMetaItem)]
136//! struct MyDescription {
137//!     name: String,
138//!     version: String,
139//! }
140//!
141//! fn my_desc_attr(
142//!     attr: proc_macro2::TokenStream,
143//!     item: proc_macro2::TokenStream,
144//! ) -> deluxe::Result<proc_macro2::TokenStream> {
145//!     let MyDescription { name, version } = deluxe::parse2::<MyDescription>(attr)?;
146//!
147//!     Ok(quote::quote! {
148//!         fn my_desc() -> &'static str {
149//!             concat!("Name: ", #name, ", Version: ", #version)
150//!         }
151//!         #item
152//!     })
153//! }
154//!
155//! # let tokens = my_desc_attr(
156//! #     quote::quote!(name = "hello world", version = "0.2"),
157//! #     quote::quote!(),
158//! # ).unwrap();
159//! # let f: syn::ItemFn = syn::parse_quote! { #tokens };
160//! # assert_eq!(f, syn::parse_quote! {
161//! #     fn my_desc() -> &'static str {
162//! #         concat!("Name: ", "hello world", ", Version: ", "0.2")
163//! #     }
164//! # });
165//! ```
166//!
167//! ```ignore
168//! // In your macros crate
169//!
170//! #[proc_macro_attribute]
171//! pub fn my_desc(
172//!     attr: proc_macro::TokenStream,
173//!     item: proc_macro::TokenStream,
174//! ) -> proc_macro::TokenStream {
175//!     my_desc_attr(attr.into(), item.into()).unwrap().into()
176//! }
177//! ```
178//!
179//! ```ignore
180//! // In your normal code
181//!
182//! #[my_desc(name = "hello world", version = "0.2")]
183//! fn nothing() {}
184//!
185//! assert_eq!(my_desc(), "Name: hello world, Version: 0.2");
186//! ```
187//!
188//! #### Field Attributes
189//!
190//! The attributes [`alias`](macro@ParseMetaItem#deluxealias--ident-1),
191//! [`default`](macro@ParseMetaItem#deluxedefault-1),
192//! [`rename`](macro@ParseMetaItem#deluxerename--ident-1), and
193//! [`skip`](macro@ParseMetaItem#deluxeskip-1) are supported, and behave the same as in Serde. The
194//! [`append`](macro@ParseMetaItem#deluxeappend) attribute can be used on [`Vec`] fields to
195//! aggregate all duplicates of a key. The [`rest`](macro@ParseMetaItem#deluxerest) attribute can
196//! be used to do custom processing on any unknown keys.
197//!
198//! ```
199//! #[derive(deluxe::ExtractAttributes)]
200//! #[deluxe(attributes(my_object))]
201//! struct MyObject {
202//!     // Can be specified with key `id` or `object_id`
203//!     #[deluxe(alias = object_id)]
204//!     id: u64,
205//!
206//!     // Field is optional, defaults to `Default::default` if not present
207//!     #[deluxe(default)]
208//!     count: u64,
209//!
210//!     // Defaults to "Empty" if not present
211//!     #[deluxe(default = String::from("Empty"))]
212//!     contents: String,
213//!
214//!     // Can be specified only with key `name`
215//!     #[deluxe(rename = name)]
216//!     s: String,
217//!
218//!     // Skipped during parsing entirely
219//!     #[deluxe(skip)]
220//!     internal_flag: bool,
221//!
222//!     // Appends any extra fields with the key `expr` to the Vec
223//!     #[deluxe(append, rename = expr)]
224//!     exprs: Vec<syn::Expr>,
225//!
226//!     // Adds any unknown keys to the hash map
227//!     #[deluxe(rest)]
228//!     rest: std::collections::HashMap<syn::Path, syn::Expr>,
229//! }
230//! ```
231//!
232//! ```ignore
233//! // Omitted fields will be set to defaults
234//! #[derive(MyObject)]
235//! #[my_object(id = 1, name = "First", expr = 1 + 2, count = 3)]
236//! struct FirstObject;
237//!
238//! // `expr` can be specified multiple times because of the `append` attribute
239//! #[derive(MyObject)]
240//! #[my_object(object_id = 2, name = "Second", expr = 1 + 2, expr = 3 + 4)]
241//! struct SecondObject;
242//!
243//! // `unknown` and `extra` will be stored in the `rest` hashmap
244//! #[derive(MyObject)]
245//! #[my_object(id = 3, name = "Third", unknown = 1 + 2, extra = 3 + 4)]
246//! struct ThirdObject;
247//! ```
248//!
249//! #### Inheritance
250//!
251//! The [`flatten`](macro@ParseMetaItem#deluxeflatten-1) attribute can be used to parse keys from
252//! one structure inside another:
253//!
254//! ```
255//! #[derive(deluxe::ParseMetaItem)]
256//! struct A {
257//!     id: u64,
258//! }
259//!
260//! #[derive(deluxe::ExtractAttributes)]
261//! #[deluxe(attributes(b))]
262//! struct B {
263//!     #[deluxe(flatten)]
264//!     a: A,
265//!     name: String,
266//! }
267//! ```
268//!
269//! Then, fields from both `A` and `B` can be used when deriving `B`:
270//!
271//! ```ignore
272//! #[derive(B)]
273//! #[b(id = 123, name = "object")]
274//! struct Object;
275//! ```
276//!
277//! #### Attributes in Nested Code
278//!
279//! Extra attributes can be taken from within the code block attached to a macro. When used in an
280//! attribute macro, the attributes should be consumed so as not to produce an "unknown attribute"
281//! error when outputting tokens.
282//!
283//! ```
284//! #[derive(deluxe::ParseMetaItem, deluxe::ExtractAttributes)]
285//! struct MyDescription {
286//!     name: String,
287//!     version: String,
288//! }
289//!
290//! #[derive(deluxe::ExtractAttributes)]
291//! #[deluxe(attributes(author))]
292//! struct Authors(#[deluxe(flatten)] Vec<String>);
293//!
294//! fn my_derive(item: proc_macro2::TokenStream) -> deluxe::Result<proc_macro2::TokenStream> {
295//!     let mut input = syn::parse2::<syn::DeriveInput>(item)?;
296//!     let MyDescription { name, version } = deluxe::extract_attributes(&mut input)?;
297//!     let mut authors = Vec::new();
298//!     if let syn::Data::Struct(s) = &mut input.data {
299//!          // Look through all fields in the struct for `author` attributes
300//!         for field in s.fields.iter_mut() {
301//!             let Authors(a) = deluxe::extract_attributes(field)?;
302//!             authors.extend(a);
303//!         }
304//!     }
305//!
306//!     let ident = &input.ident;
307//!     let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
308//!
309//!     Ok(quote::quote! {
310//!         impl #impl_generics #ident #type_generics #where_clause {
311//!             fn my_desc() -> &'static str {
312//!                 concat!("Name: ", #name, ", Version: ", #version #(, ", Author: ", #authors)*)
313//!             }
314//!         }
315//!     })
316//! }
317//!
318//! # let tokens = my_derive(quote::quote! {
319//! #     #[my_desc(name = "hello world", version = "0.2")]
320//! #     struct Hello(#[author("Alice")] String);
321//! # }).unwrap();
322//! # let i: syn::ItemImpl = syn::parse_quote! { #tokens };
323//! # assert_eq!(i, syn::parse_quote! {
324//! #     impl Hello {
325//! #         fn my_desc() -> &'static str {
326//! #             concat!("Name: ", "hello world", ", Version: ", "0.2", ", Author: ", "Alice")
327//! #         }
328//! #     }
329//! # });
330//!
331//! fn my_desc_mod(
332//!     attr: proc_macro2::TokenStream,
333//!     item: proc_macro2::TokenStream,
334//! ) -> deluxe::Result<proc_macro2::TokenStream> {
335//!     let MyDescription { name, version } = deluxe::parse2::<MyDescription>(attr)?;
336//!     let mut authors = Vec::new();
337//!     let mut module = syn::parse2::<syn::ItemMod>(item)?;
338//!
339//!     let (_, items) = module.content.as_mut().unwrap();
340//!
341//!     // Look through all items in the module for `author` attributes
342//!     for i in items.iter_mut() {
343//!         // Extract the attributes to remove them from the final output
344//!         let Authors(a) = deluxe::extract_attributes(i)?;
345//!         authors.extend(a);
346//!     }
347//!
348//!     // Place a new function inside the module
349//!     items.push(syn::parse_quote! {
350//!         fn my_desc() -> &'static str {
351//!             concat!("Name: ", #name, ", Version: ", #version #(, ", Author: ", #authors)*)
352//!         }
353//!     });
354//!
355//!     Ok(quote::quote! { #module })
356//! }
357//!
358//! # let tokens = my_desc_mod(
359//! #     quote::quote!(name = "hello world", version = "0.2"),
360//! #     quote::quote!(mod abc {
361//! #         #[author("Alice", "Bob")]
362//! #         fn func1() {}
363//! #         #[author("Carol")]
364//! #         #[author("Dave")]
365//! #         fn func2() {}
366//! #     }),
367//! # ).unwrap();
368//! # let m: syn::ItemMod = syn::parse_quote! { #tokens };
369//! # assert_eq!(m, syn::parse_quote! {
370//! #     mod abc {
371//! #         fn func1() {}
372//! #         fn func2() {}
373//! #         fn my_desc() -> &'static str {
374//! #             concat!(
375//! #                 "Name: ", "hello world", ", Version: ", "0.2",
376//! #                 ", Author: ", "Alice", ", Author: ", "Bob",
377//! #                 ", Author: ", "Carol", ", Author: ", "Dave"
378//! #             )
379//! #         }
380//! #     }
381//! # });
382//! ```
383//!
384//! ```ignore
385//! // In your normal code
386//!
387//! #[derive(MyDescription, Default)]
388//! #[my_desc(name = "hello world", version = "0.2")]
389//! struct Hello {
390//!     #[author("Alice")]
391//!     a: i32,
392//!     #[author("Bob")]
393//!     b: String
394//! }
395//!
396//! let hello: Hello = Default::default();
397//! assert_eq!(hello.my_desc(), "Name: hello world, Version: 0.2, Author: Alice, Author: Bob");
398//!
399//! #[my_desc_mod(name = "hello world", version = "0.2")]
400//! mod abc {
401//!     #[author("Alice", "Bob")]
402//!     fn func1() {}
403//!
404//!     #[author("Carol")]
405//!     #[author("Dave")]
406//!     fn func2() {}
407//! }
408//!
409//! assert_eq!(
410//!     abc::my_desc(),
411//!     "Name: hello world, Version: 0.2, Author: Alice, Author: Bob, Author: Carol, Author: Dave"
412//! );
413//! ```
414//!
415//! #### Tuple Structs, Tuples and Vecs
416//!
417//! Deluxe also supports parsing into data structures with unnamed fields.
418//!
419//! ```
420//! #[derive(deluxe::ExtractAttributes)]
421//! #[deluxe(attributes(my_tuple))]
422//! struct MyTuple(u64, String);
423//!
424//! #[derive(deluxe::ExtractAttributes)]
425//! #[deluxe(attributes(my_idents))]
426//! struct MyIdents {
427//!     id: u64,
428//!     names: (String, String),
429//!     idents: Vec<syn::Ident>
430//! }
431//! ```
432//!
433//! The standard attribute syntax with parenthesis can be used when specifying a [`Vec`] type. The
434//! alternative syntax `key = [...]` can also be used to have an appearance similar to an array
435//! literal.
436//!
437//! ```ignore
438//! #[derive(MyTuple)]
439//! #[my_tuple(123, "object")]
440//! struct Object;
441//!
442//! #[derive(MyIdents)]
443//! #[my_idents(id = 7, names("hello", "world"), idents(a, b, c))]
444//! struct ABC;
445//!
446//! // `idents` contains same values as above
447//! #[derive(MyIdents)]
448//! #[my_idents(id = 7, names("hello", "world"), idents = [a, b, c])]
449//! struct ABC2;
450//! ```
451//!
452//! #### C#-styled Attributes
453//!
454//! Attributes in C# can support positional arguments first with the named
455//! arguments afterwards. This style can be emulated by using a tuple struct with a
456//! normal struct flattened at the end. Placing
457//! [`#[deluxe(default)]`](macro@ParseMetaItem#deluxedefault) on the struct behaves the same as
458//! Serde, by filling in all fields with values from [`Default`], allowing every named argument to
459//! be optional.
460//!
461//! ```
462//! #[derive(deluxe::ParseMetaItem, Default)]
463//! #[deluxe(default)]
464//! struct Flags {
465//!     native: bool,
466//! }
467//!
468//! #[derive(deluxe::ExtractAttributes)]
469//! #[deluxe(attributes(a))]
470//! struct A(u64, String, #[deluxe(flatten)] Flags);
471//! ```
472//!
473//! ```ignore
474//! #[derive(A)]
475//! #[a(123, "object")]
476//! struct Object;
477//!
478//! #[derive(A)]
479//! #[a(123, "native-object", native = true)]
480//! struct NativeObject;
481//! ```
482//!
483//! #### Enums
484//!
485//! Enums are supported by using the variant name as a single key, in snake-case. Variants can be
486//! renamed, aliased and skipped in the same way as fields.
487//!
488//! ```
489//! #[derive(deluxe::ExtractAttributes)]
490//! #[deluxe(attributes(my_enum))]
491//! enum MyEnum {
492//!     A,
493//!     B,
494//!     C,
495//!     #[deluxe(alias = d)]
496//!     AnotherOne,
497//!     #[deluxe(rename = e)]
498//!     AnotherTwo,
499//!     #[deluxe(skip)]
500//!     SkipMe
501//! }
502//! ```
503//!
504//! ```ignore
505//! #[derive(MyEnum)]
506//! #[my_enum(b)]
507//! struct ObjectB;
508//!
509//! #[derive(MyEnum)]
510//! #[my_enum(another_one)]
511//! struct ObjectD;
512//! ```
513//!
514//! #### Complex Enums
515//!
516//! Enums with struct and tuple variants are also supported. The data inside is used as arguments
517//! to the attribute. All field attributes from structs are also supported inside variants.
518//!
519//! Additionally, enum variants with named fields can be flattened. The behavior of a flattened
520//! variant is similar to Serde's `untagged` mode. In a flattened variant, the name of the variant
521//! will be ignored. Instead, Deluxe will attempt to use the unique keys in each variant to
522//! determine if that variant was specified. A compile error will be thrown if it is not possible
523//! to determine a unique, unambiguous key between two variants.
524//!
525//! ```
526//! #[derive(deluxe::ExtractAttributes)]
527//! #[deluxe(attributes(my_enum))]
528//! enum MyEnum {
529//!     A,
530//!     B(u64, String),
531//!     C { id: u64, name: String },
532//!     #[deluxe(flatten)]
533//!     D { d: u64, name: String },
534//! }
535//! ```
536//!
537//! ```ignore
538//! #[derive(MyEnum)]
539//! #[my_enum(a)]
540//! struct ObjectA;
541//!
542//! #[derive(MyEnum)]
543//! #[my_enum(b(1, "hello"))]
544//! struct ObjectB;
545//!
546//! #[derive(MyEnum)]
547//! #[my_enum(c(id = 2, name = "world"))]
548//! struct ObjectC;
549//!
550//! // No inner parenthesis needed here due to flattening
551//! #[derive(MyEnum)]
552//! #[my_enum(d = 3, name = "moon")]
553//! struct ObjectD;
554//! ```
555//!
556//! #### Storing Containers
557//!
558//! During parsing, Deluxe can store references to the container type holding the attributes for
559//! easier access. Container fields are skipped during attribute parsing.
560//!
561//! ```
562//! #[derive(deluxe::ParseAttributes)]
563//! #[deluxe(attributes(my_object))]
564//! struct MyObject<'t> {
565//!     id: u64,
566//!     // Fill `container` in using the parsed type. Note this restricts the
567//!     // derived `ParseAttributes` impl so it can only be used on `DeriveInput`.
568//!     #[deluxe(container)]
569//!     container: &'t syn::DeriveInput,
570//! }
571//!
572//! fn my_object(item: proc_macro2::TokenStream) -> deluxe::Result<proc_macro2::TokenStream> {
573//!     let input = syn::parse2::<syn::DeriveInput>(item)?;
574//!
575//!     // `obj.container` now holds a reference to `input`
576//!     let obj: MyObject = deluxe::parse_attributes(&input)?;
577//!
578//!     Ok(quote::quote! { /* ... generate some code here ... */ })
579//! }
580//! ```
581//!
582//! To support both extracting and parsing, a container field can also be a value type. In that
583//! case, the container will be cloned into the structure.
584
585#![deny(missing_docs)]
586#![deny(unsafe_code)]
587
588#[doc(hidden)]
589pub mod ____private {
590    pub use deluxe_core::parse_helpers::{self, FieldStatus, SmallString};
591    pub use once_cell::sync::OnceCell as SyncOnceCell;
592    pub use proc_macro2::Span;
593    pub use std::{
594        borrow::{Borrow, Cow, ToOwned},
595        clone::Clone,
596        collections::HashMap,
597        convert::{AsRef, From},
598        default::Default,
599        format, format_args,
600        iter::IntoIterator,
601        option::Option,
602        primitive::{bool, str, usize},
603        string::{String, ToString},
604        unreachable,
605        vec::Vec,
606    };
607    pub use syn::{
608        parse::{ParseBuffer, ParseStream},
609        Error, Ident, Path,
610    };
611}
612
613pub use deluxe_core::{
614    define_with_collection, define_with_map, define_with_optional, parse_named_meta_item_with,
615    with, Error, Errors, ExtractAttributes, Flag, HasAttributes, ParseAttributes, ParseMetaItem,
616    ParseMode, Result, SpannedValue,
617};
618#[doc(hidden)]
619pub use deluxe_core::{
620    ContainerFrom, ParseMetaAppend, ParseMetaFlatNamed, ParseMetaFlatUnnamed, ParseMetaRest,
621    ToKeyString,
622};
623pub use deluxe_macros::*;
624
625/// Additional helper functions for validating after parsing.
626pub mod validations {
627    pub use deluxe_core::validations::*;
628    pub use deluxe_core::{all_or_none, only_one};
629}
630
631#[cfg(feature = "proc-macro")]
632extern crate proc_macro;
633
634/// Parses a required Rust type out of a token stream.
635///
636/// Intended for use with [attribute
637/// macros](https://doc.rust-lang.org/stable/reference/procedural-macros.html#attribute-macros).
638/// This is a small wrapper around [`syn::parse::Parser::parse`] and
639/// [`ParseMetaItem::parse_meta_item_inline`].
640#[cfg(feature = "proc-macro")]
641#[inline]
642pub fn parse<T: ParseMetaItem>(attr: proc_macro::TokenStream) -> Result<T> {
643    syn::parse::Parser::parse(
644        |stream: syn::parse::ParseStream<'_>| {
645            T::parse_meta_item_inline(&[stream], ParseMode::Named(proc_macro2::Span::call_site()))
646        },
647        attr,
648    )
649}
650
651/// Parses a required Rust type out of a token stream.
652///
653/// Intended for use with [attribute
654/// macros](https://doc.rust-lang.org/stable/reference/procedural-macros.html#attribute-macros).
655/// This is a small wrapper around [`syn::parse::Parser::parse2`] and
656/// [`ParseMetaItem::parse_meta_item_inline`].
657#[inline]
658pub fn parse2<T: ParseMetaItem>(attr: proc_macro2::TokenStream) -> Result<T> {
659    syn::parse::Parser::parse2(
660        |stream: syn::parse::ParseStream<'_>| {
661            T::parse_meta_item_inline(&[stream], ParseMode::Named(proc_macro2::Span::call_site()))
662        },
663        attr,
664    )
665}
666
667/// Parses a required Rust type out of another type holding a list of [`syn::Attribute`].
668///
669/// Intended for use with [derive
670/// macros](https://doc.rust-lang.org/stable/reference/procedural-macros.html#derive-macros). This
671/// is a small wrapper around [`ParseAttributes::parse_attributes`].
672#[inline]
673pub fn parse_attributes<'t, T, R>(obj: &'t T) -> Result<R>
674where
675    T: HasAttributes,
676    R: ParseAttributes<'t, T>,
677{
678    R::parse_attributes(obj)
679}
680
681/// Extracts attributes out of another type holding a list of [`syn::Attribute`], then parses them
682/// into a required Rust type.
683///
684/// Intended for use with [derive
685/// macros](https://doc.rust-lang.org/stable/reference/procedural-macros.html#derive-macros). This
686/// is a small wrapper around [`ExtractAttributes::extract_attributes`].
687#[inline]
688pub fn extract_attributes<T, R>(obj: &mut T) -> Result<R>
689where
690    T: HasAttributes,
691    R: ExtractAttributes<T>,
692{
693    R::extract_attributes(obj)
694}
695
696/// Parses a Rust type out of a token stream, returning a default value on failure.
697///
698/// Calls [`parse`] and returns the result. Upon failure, [`Default::default`] will be returned and
699/// any errors will be appended to `errors`. This function should be preferred when parsing
700/// multiple attributes, so the errors from all of them can be accumulated instead of returning
701/// early.
702#[cfg(feature = "proc-macro")]
703#[inline]
704pub fn parse_optional<T: ParseMetaItem + Default>(
705    attr: proc_macro::TokenStream,
706    errors: &Errors,
707) -> T {
708    match parse(attr) {
709        Ok(t) => t,
710        Err(e) => {
711            errors.push_syn(e);
712            Default::default()
713        }
714    }
715}
716
717/// Parses a Rust type out of a token stream, returning a default value on failure.
718///
719/// Calls [`parse2`] and returns the result. Upon failure, [`Default::default`] will be returned
720/// and any errors will be appended to `errors`. This function should be preferred when parsing
721/// multiple attributes, so the errors from all of them can be accumulated instead of returning
722/// early.
723#[inline]
724pub fn parse2_optional<T: ParseMetaItem + Default>(
725    attr: proc_macro2::TokenStream,
726    errors: &Errors,
727) -> T {
728    match parse2(attr) {
729        Ok(t) => t,
730        Err(e) => {
731            errors.push_syn(e);
732            Default::default()
733        }
734    }
735}
736
737/// Parses a Rust type out of another type holding a list of [`syn::Attribute`], returning a default value on failure.
738///
739/// Calls [`parse_attributes`] and returns the result. Upon failure, [`Default::default`] will be
740/// returned and any errors will be appended to `errors`. This function should be preferred when
741/// parsing multiple attributes, so the errors from all of them can be accumulated instead of
742/// returning early.
743#[inline]
744pub fn parse_attributes_optional<'t, T, R>(obj: &'t T, errors: &Errors) -> R
745where
746    T: HasAttributes,
747    R: ParseAttributes<'t, T> + Default,
748{
749    match parse_attributes(obj) {
750        Ok(t) => t,
751        Err(e) => {
752            errors.push_syn(e);
753            Default::default()
754        }
755    }
756}
757
758/// Extracts attributes out of another type holding a list of [`syn::Attribute`], then parses them
759/// into a Rust type, returning a default value on failure.
760///
761/// Calls [`extract_attributes`] and returns the result. Upon failure, [`Default::default`] will be
762/// returned and any errors will be appended to `errors`. This function should be preferred when
763/// parsing multiple attributes, so the errors from all of them can be accumulated instead of
764/// returning early.
765#[inline]
766pub fn extract_attributes_optional<T, R>(obj: &mut T, errors: &Errors) -> R
767where
768    T: HasAttributes,
769    R: ExtractAttributes<T> + Default,
770{
771    match extract_attributes(obj) {
772        Ok(t) => t,
773        Err(e) => {
774            errors.push_syn(e);
775            Default::default()
776        }
777    }
778}