Skip to main content

Crate macro_rules_attr

Crate macro_rules_attr 

Source
Expand description

§macro_rules_attr

GitHub License Crates.io Version Crates.io Total Downloads docs.rs free of syn

Use declarative macros as proc_macro attributes. (#[apply] / #[extend] your macro_rules!)

§Usage

§#[apply]

First, bring the apply attribute macro into scope:

use macro_rules_attr::apply;

Then, define your macro using macro_rules!:

/// Your macro that you want to use as an attribute.
macro_rules! the_macro {
    // Your macro implementation here.
}

Finally, annotate your item with the apply attribute macro:

#[apply(the_macro)]
struct One {}
// Expands to:
the_macro! { struct One {} }

Additional tokens are appended after the annotated item:

#[apply(the_macro, "additional tokens", anything, (you - like))]
struct Another {}
// Expands to:
the_macro! { struct Another {}, "additional tokens", anything, (you - like) }

§#[extend]

The extend attribute macro works like apply, but it keeps the original item instead of consuming it, similar to how #[derive] works. For example:

use macro_rules_attr::extend;

/// Simple macro that generates a `hello` function for given struct, which returns `Hello, {name}!`. If given a second argument, it will replace `{name}`.
macro_rules! make_hello {
( // Matches a struct definition (some details omitted for brevity)
    struct $StructName:ident {
        // ...
    }$(, $replacement:expr)?
) => {
    // You don't have to repeat the original struct definition, since `#[extend]` will keep it.
    // Implement the `hello` function
    impl $StructName {
        fn hello() -> String {
            let name = stringify!($StructName);
            $(let name = $replacement;)? // Shadow `name` if a replacement was provided
            format!("Hello, {name}!")
        }
    }
};
}

#[extend(make_hello)] // No additional tokens
struct WithoutReplacement {}
assert_eq!(WithoutReplacement::hello(), "Hello, WithoutReplacement!");

#[extend(make_hello, "World")] // Additional tokens
struct WithReplacement {}
assert_eq!(WithReplacement::hello(), "Hello, World!");

§Cargo Features

  • log: Enable logging with the log crate. (Requires log as a dependency)

§Comparison

This crate is heavily inspired by macro_rules_attribute, but differs in the following ways:

  • macro_rules_attr is more lightweight and has no dependencies by default.
    • Less than 100 lines of code. (Excluding tests and documentation)
    • You can enable logging with the log feature, which requires log as a dependency.
    • paste is required as a dev-dependency for the tests.
  • macro_rules_attr only has #[apply] and #[extend], while macro_rules_attribute provides more.
  • macro_rules_attr allows you to append any tokens after the annotated item, while macro_rules_attribute does not.

Attribute Macros§

apply
Apply the given macro to the annotated item, appending additional tokens if provided.
extend
Extend the annotated item by applying the given macro and appending additional tokens if provided.