8 releases

0.1.6 Aug 30, 2020
0.1.5 Jul 11, 2020
0.1.4 Mar 4, 2020
0.1.2 Nov 28, 2019
0.0.1 Nov 28, 2019

#130 in Procedural macros

Download history 4147/week @ 2021-08-11 4777/week @ 2021-08-18 5021/week @ 2021-08-25 6708/week @ 2021-09-01 8839/week @ 2021-09-08 11983/week @ 2021-09-15 13545/week @ 2021-09-22 15810/week @ 2021-09-29 15708/week @ 2021-10-06 15903/week @ 2021-10-13 14061/week @ 2021-10-20 11527/week @ 2021-10-27 13960/week @ 2021-11-03 10402/week @ 2021-11-10 8497/week @ 2021-11-17 3976/week @ 2021-11-24

39,105 downloads per month
Used in 9 crates (4 directly)

MIT license

13KB
237 lines

bae

bae is a crate for proc macro authors, which simplifies parsing of attributes. It is heavily inspired by darling but has a significantly simpler API.

See the docs for more info.


lib.rs:

bae is a crate for proc macro authors, which simplifies parsing of attributes. It is heavily inspired by darling but has a significantly simpler API.

use bae::FromAttributes;

#[derive(
    Debug,
    Eq,
    PartialEq,

    // This will add two functions:
    // ```
    // fn from_attributes(attrs: &[syn::Attribute]) -> Result<MyAttr, syn::Error>
    // fn try_from_attributes(attrs: &[syn::Attribute]) -> Result<Option<MyAttr>, syn::Error>
    // ```
    //
    // `try_from_attributes` returns `Ok(None)` if the attribute is missing, `Ok(Some(_))` if
    // its there and is valid, `Err(_)` otherwise.
    FromAttributes,
)]
pub struct MyAttr {
    // Anything that implements `syn::parse::Parse` is supported.
    mandatory_type: syn::Type,
    mandatory_ident: syn::Ident,

    // Fields wrapped in `Option` are optional and default to `None` if
    // not specified in the attribute.
    optional_missing: Option<syn::Type>,
    optional_given: Option<syn::Type>,

    // A "switch" is something that doesn't take arguments.
    // All fields with type `Option<()>` are considered swiches.
    // They default to `None`.
    switch: Option<()>,
}

// `MyAttr` is now equipped to parse attributes named `my_attr`. For example:
//
//     #[my_attr(
//         switch,
//         mandatory_ident = foo,
//         mandatory_type = SomeType,
//         optional_given = OtherType,
//     )]
//     struct Foo {
//         ...
//     }

// the input and output type would normally be `proc_macro::TokenStream` but those
// types cannot be used outside the compiler itself.
fn my_proc_macro(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    let item_struct = syn::parse2::<syn::ItemStruct>(input).unwrap();

    let my_attr = MyAttr::from_attributes(&item_struct.attrs).unwrap();

    assert_eq!(
        my_attr.mandatory_type,
        syn::parse_str::<syn::Type>("SomeType").unwrap()
    );

    assert_eq!(my_attr.optional_missing, None);

    assert_eq!(
        my_attr.optional_given,
        Some(syn::parse_str::<syn::Type>("OtherType").unwrap())
    );

    assert_eq!(my_attr.mandatory_ident, syn::parse_str::<syn::Ident>("foo").unwrap());

    assert_eq!(my_attr.switch.is_some(), true);

    // ...
    #
    # quote::quote! {}
}
#
# fn main() {
#     let code = quote::quote! {
#         #[other_random_attr]
#         #[my_attr(
#             switch,
#             mandatory_ident = foo,
#             mandatory_type = SomeType,
#             optional_given = OtherType,
#         )]
#         struct Foo;
#     };
#     my_proc_macro(code);
# }

Dependencies

~0.8–1.3MB
~25K SLoC

=K_