#proc-macro-attributes #macro-rules #proc-macro #decorator #attributes #macro-attributes

macro no-std macro_rules_attr

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

4 releases

Uses new Rust 2024

new 0.1.3 Mar 30, 2025
0.1.2 Mar 28, 2025
0.1.1 Mar 26, 2025
0.1.0 Mar 26, 2025

#1986 in Procedural macros

Download history 416/week @ 2025-03-25

416 downloads per month
Used in 3 crates

MIT license

9KB

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] your macro_rules!)

Usage

First, bring the apply attribute macro into scope:

use macro_rules_attr::apply;

Then, define your macro using macro_rules!:

# use macro_rules_attr::apply;
#
/// Your macro that you want to use as an attribute.
macro_rules! the_macro {
    // Your macro implementation here.
#     ($($tt:tt)*) => {}; // Matches and discards everything.
}

Finally, annotate your item with the apply attribute macro:

# use macro_rules_attr::apply;
#
# /// Your macro that you want to use as an attribute.
# macro_rules! the_macro {
#     // Your macro implementation here.
#     ($($tt:tt)*) => {}; // Matches and discards everything.
# }
#
#[apply(the_macro)]
struct One {}
// Expands to:
the_macro! { struct One {} }

Additional tokens are appended after the annotated item:

# use macro_rules_attr::apply;
#
# /// Your macro that you want to use as an attribute.
# macro_rules! the_macro {
#     // Your macro implementation here.
#     ($($tt:tt)*) => {}; // Matches and discards everything.
# }
#
#[apply(the_macro, "additional tokens", anything, (you - like))]
struct Another {}
// Expands to:
the_macro! { struct Another {}, "additional tokens", anything, (you - like) }

Example

use macro_rules_attr::apply;

/// 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_meta:meta])*
#     $struct_vis:vis
    struct $StructName:ident {
        // ...
#         $(
#             $(#[$field_meta:meta])*
#             $field_vis:vis
#             $field_name:ident : $field_ty:ty
#         ),* $(,)?
    }$(, $replacement:expr)?
) => {
    // Repeat the struct definition
#     $(#[$struct_meta])*
#     $struct_vis
    struct $StructName {
        // ...
#         $(
#             $(#[$field_meta])*
#             $field_vis:vis $field_name: $field_ty,
#         )*
    }

    // 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}!")
        }
    }
};
}

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

#[apply(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 one attribute: #[apply], 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.

Dependencies

~23KB