#macro-derive #attributes #macro #derive #custom #custom-derive

no-std macro-attr

This crate provides the macro_attr! macro that enables the use of custom, macro-based attributes and derivations. Supercedes the custom_derive crate.

1 unstable release

Uses old Rust 2015

0.2.0 Nov 21, 2016

#1996 in Rust patterns

Download history 102/week @ 2023-11-28 77/week @ 2023-12-05 108/week @ 2023-12-12 117/week @ 2023-12-19 93/week @ 2023-12-26 185/week @ 2024-01-02 234/week @ 2024-01-09 166/week @ 2024-01-16 102/week @ 2024-01-23 162/week @ 2024-01-30 137/week @ 2024-02-06 132/week @ 2024-02-13 106/week @ 2024-02-20 182/week @ 2024-02-27 218/week @ 2024-03-05 175/week @ 2024-03-12

701 downloads per month
Used in 11 crates (10 directly)

MIT/Apache

54KB
1K SLoC

Rust 841 SLoC // 0.3% comments Python 353 SLoC // 0.1% comments

macro-attr

This crate provides the macro_attr! macro that enables the use of custom, macro-based attributes and derivations. Supercedes the custom_derive crate.

Links

Compatibility

macro-attr is compatible with Rust 1.2 and higher.

Example

#[macro_use] extern crate macro_attr;

// Define some traits to be derived.

trait TypeName {
    fn type_name() -> &'static str;
}

trait ReprType {
    type Repr;
}

// Define macros which derive implementations of these macros.

macro_rules! TypeName {
    // We can support any kind of item we want.
    (() $(pub)* enum $name:ident $($tail:tt)*) => { TypeName! { @impl $name } };
    (() $(pub)* struct $name:ident $($tail:tt)*) => { TypeName! { @impl $name } };

    // Inner rule to cut down on repetition.
    (@impl $name:ident) => {
        impl TypeName for $name {
            fn type_name() -> &'static str { stringify!($name) }
        }
    };
}

macro_rules! ReprType {
    // Note that we use a "derivation argument" here for the `$repr` type.
    (($repr:ty) $(pub)* enum $name:ident $($tail:tt)*) => {
        impl ReprType for $name {
            type Repr = $repr;
        }
    };
}

// Here is a macro that *modifies* the item.

macro_rules! rename_to {
    (
        ($new_name:ident),
        then $cb:tt,
        $(#[$($attrs:tt)*])*
        enum $_old_name:ident $($tail:tt)*
    ) => {
        macro_attr_callback! {
            $cb,
            $(#[$($attrs)*])*
            enum $new_name $($tail)*
        }
    };
}

macro_attr! {
    #[allow(dead_code)]
    #[derive(Clone, Copy, Debug, ReprType!(u8), TypeName!)]
    #[rename_to!(Bar)]
    #[repr(u8)]
    enum Foo { A, B }
}

fn main() {
    let bar = Bar::B;
    let v = bar as <Bar as ReprType>::Repr;
    let msg = format!("{}: {:?} ({:?})", Bar::type_name(), bar, v);
    assert_eq!(msg, "Bar: B (1)");
}

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.

No runtime deps