macro-template
macro-template is a procedural macro that generates repeated Rust code in multiple places with table-driven inputs.
Motivations
This crate is inspired by match-template and macro_find_and_replace.
When developing ScopeDB, we introduced these two proc-macros to generate repeated code for match arms and impls. I noticed that they share a common pattern: iterating over a table of values and generating code based on it. I wanted to unify these patterns into a single, concise, but flexible macro that can handle various use cases. That's how macro-template was born.
Last but not least, I found seq-macro and borrowed some ideas from it, such as iterating over a range of numbers, characters, or bytes, and using a syntax @splice { } (equivalent to seq-macro's or quote's #( ... )*) to generate partial repeated substitutions. This eliminates the need for an extra template_match! to handle repetitions in match arms, and allows for more flexible code generation.
Go back to the beginning, why do you need macro_template:template! at all? Isn't it the same as a simple macro_rules!?
impl_serialize!;
Except that macro_template:template! supports more flexible substitution patterns as shown in the Examples section, template! has a concise syntax, and it saves you from declaring an extra macro_rules! (Naming It!) and invoking it.
The example above can be rewritten as:
template!
Examples
Firstly, the following code generates From implementations for MyEnum from all its variants:
template!
You can iterate over a matrix as well:
template!
Or, you can generate repeated match arms by pattern:
template!
When a template contains @splice, template variables are substituted only inside @splice { ... }. Surrounding tokens stay literal, even when an identifier has the same name as a template variable. If a value should vary, place it in the splice block.
Naturally, if the match arm differs left-hand side and right-hand side:
template!
The iterator can be a sequence of numbers, characters, or bytes:
// sequential numeric counter
let tuple = ;
let mut sum = 0;
template!
assert_eq!;
// sequential character collector
let mut string = Stringnew;
template!
assert_eq!;
You can combine multiple iterators in a single template:
let mut values = vec!;
template!
assert_eq!;
Minimum Rust version policy
This crate's minimum supported rustc version is 1.85.0.
The current policy is that the minimum Rust version required to use this crate can be increased in minor version updates. For example, if crate 1.0 requires Rust 1.85.0, then crate 1.0.z for all values of z will also require Rust 1.85.0 or newer. However, crate 1.y for y > 0 may require a newer minimum version of Rust.
License
This project is licensed under Apache License, Version 2.0.