compose-idents
A macro for generating new identifiers (names of variables, functions, traits, etc.) by concatenating one or more arbitrary parts and applying other manipulations.
It was created as an alternative to macro_rules! that doesn't allow creating new identifiers from the macro arguments
and concat_idents! macro from the nightly Rust, which is limited in capabilities and has not been stabilized
since 2015.
Features
-
Identifier generation
Identifiers can be generated via concatenation of multiple parts. Arguments of the outer macro definitions and literals are supported for identifier definitions.
-
Functions
Functions can be applied when defining new identifiers for changing case and style.
-
String formatting
Strings can be formatted with
%alias%syntax, which is useful for generating doc-attributes.
Usage
This section contains various usage examples. For even more usage examples look into tests/ directory
of the repository.
Quick start example
compose_idents! works by accepting definitions of aliases and a code block where aliases
could be used as normal identifiers. When the macro is expanded, the aliases are replaced with their
definitions:
use compose_idents;
// We generate separate const-functions for each type as a workaround
// since Rust doesn't allow us to use `core::ops::Add` in `const fn`.
gen_const_add!; // Expands into `add_u32()` function.
gen_const_add!; // Expands into `add_u64()` function.
assert_eq!;
assert_eq!;
Generating tests for different types
Another practical example for how to auto-generate names for macro-generated tests for different data types:
use Add;
use compose_idents;
// Generates tests for u8, u32 and u64 types
generate_add_tests!;
test_add_u8;
test_add_u32;
test_add_u64;
Reference example
This example includes all the features of the macro:
use compose_idents;
compose_idents!;
// It's possible to use arguments of declarative macros as parts of the identifiers.
outer_macro!;
global_var_macro!;
global_var_macro!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Functions
| Function | Description |
|---|---|
upper(arg) |
Converts the arg to upper case. |
lower(arg) |
Converts the arg to lower case. |
snake_case(arg) |
Converts the arg to snake_case. |
camel_case(arg) |
Converts the arg to camelCase. |
hash(arg) |
Hashes the arg deterministically within a single macro invocation. |
Alternatives
There some other tools and projects dedicated to identifier manipulation:
- A macro from Nightly Rust that allows to concatenate identifiers. It is limited in functionality and nowhere near to be stabilized: https://doc.rust-lang.org/std/macro.concat_idents.html
- A very similar macro that doesn't support multiple aliases and is not maintained: https://github.com/DzenanJupic/concat-idents
- A macro that allows to define and refer to unique temporary variables: https://crates.io/crates/templest
Development
The following standards are followed to maintain the project: