Macros for all your token pasting needs
=======================================
[<img alt="crates.io" src="https://img.shields.io/crates/v/macro_paste.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/macro_paste)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-macro_paste-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/macro_paste)
[](https://opensource.org/licenses/Apache-2.0)
[](https://github.com/butlergroup/macro_paste/actions/workflows/github-code-scanning/codeql)
[](https://github.com/butlergroup/macro_paste/actions/workflows/ci.yml)
[](https://github.com/butlergroup/macro_paste/actions/workflows/dependabot/dependabot-updates)
[](https://github.com/butlergroup/macro_paste/actions/workflows/cifuzz.yml)
[](https://github.com/butlergroup/macro_paste/actions/workflows/cross_platform.yml)
[](https://github.com/butlergroup/macro_paste/actions/workflows/miri.yml)
[](https://github.com/butlergroup/macro_paste/actions/workflows/rust-clippy.yml)
[](https://github.com/butlergroup/macro_paste/actions/workflows/security.yml)
[](https://github.com/butlergroup/macro_paste/actions/workflows/osv-scanner.yml)
[](https://app.snyk.io/share/784f6fef-6aaf-47ed-81ba-99e05b854665)
[](https://deps.rs/repo/github/butlergroup/macro_paste)
[](https://www.bestpractices.dev/projects/11322)
[](https://github.com/butlergroup/macro_paste/actions/workflows/scorecard.yml)
[](https://github.com/butlergroup/macro_paste/actions/workflows/defender-for-devops.yml)
[](https://coveralls.io/github/butlergroup/macro_paste?branch=master)
[](https://github.com/butlergroup/macro_paste/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement)
[](https://github.com/butlergroup/macro_paste/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Abug)
## Info on this fork
- Originally forked from paste 1.0.15
- Will be maintained (depenencies/crates updated & CVEs addressed in a timely manner, etc.)
- Will pick up where the author left off in terms of semantic versioning (author's last release version was 1.0.15, our first version is 1.1.0)
- Several security scanners have been added to the repo to ensure any issues are found quickly
- Minor code/comment additions to streamline compatibility
- Rust edition updated from 2018 to 2021 without build/unit test errors
- MSRV (minimum supported Rust version) updated from 1.31 to 1.85 without build/unit test errors
*Disclaimer:* this project is stable and can be used in production environments, but SLA-based support won't be offered until we're at v1.2 and/or sponsored. :bowtie:
## Original author's notes...
The nightly-only [`concat_idents!`] macro in the Rust standard library is
notoriously underpowered in that its concatenated identifiers can only refer to
existing items, they can never be used to define something new.
[`concat_idents!`]: https://doc.rust-lang.org/std/macro.concat_idents.html
This crate provides a flexible way to macro_paste together identifiers in a macro,
including using pasted identifiers to define new items.
```toml
[dependencies]
macro_paste = "1.0"
```
This approach works with any Rust compiler 1.31+.
## Pasting identifiers
Within the `macro_paste!` macro, identifiers inside `[<`...`>]` are pasted together to
form a single identifier.
```rust
use macro_paste::macro_paste;
macro_paste! {
// Defines a const called `QRST`.
const [<Q R S T>]: &str = "success!";
}
fn main() {
assert_eq!(
macro_paste! { [<Q R S T>].len() },
8,
);
}
```
## More elaborate example
The next example shows a macro that generates accessor methods for some struct
fields. It demonstrates how you might find it useful to bundle a macro_paste
invocation inside of a macro\_rules macro.
```rust
use macro_paste::macro_paste;
macro_rules! make_a_struct_and_getters {
($name:ident { $($field:ident),* }) => {
// Define a struct. This expands to:
//
// pub struct S {
// a: String,
// b: String,
// c: String,
// }
pub struct $name {
$(
$field: String,
)*
}
// Build an impl block with getters. This expands to:
//
// impl S {
// pub fn get_a(&self) -> &str { &self.a }
// pub fn get_b(&self) -> &str { &self.b }
// pub fn get_c(&self) -> &str { &self.c }
// }
macro_paste! {
impl $name {
$(
pub fn [<get_ $field>](&self) -> &str {
&self.$field
}
)*
}
}
}
}
make_a_struct_and_getters!(S { a, b, c });
fn call_some_getters(s: &S) -> bool {
s.get_a() == s.get_b() && s.get_c().is_empty()
}
```
## Case conversion
Use `$var:lower` or `$var:upper` in the segment list to convert an interpolated
segment to lower- or uppercase as part of the macro_paste. For example, `[<ld_
$reg:lower _expr>]` would macro_paste to `ld_bc_expr` if invoked with $reg=`Bc`.
Use `$var:snake` to convert CamelCase input to snake\_case.
Use `$var:camel` to convert snake\_case to CamelCase.
These compose, so for example `$var:snake:upper` would give you SCREAMING\_CASE.
The precise Unicode conversions are as defined by [`str::to_lowercase`] and
[`str::to_uppercase`].
[`str::to_lowercase`]: https://doc.rust-lang.org/std/primitive.str.html#method.to_lowercase
[`str::to_uppercase`]: https://doc.rust-lang.org/std/primitive.str.html#method.to_uppercase
## Pasting documentation strings
Within the `macro_paste!` macro, arguments to a #\[doc ...\] attribute are implicitly
concatenated together to form a coherent documentation string.
```rust
use macro_paste::macro_paste;
macro_rules! method_new {
($ret:ident) => {
macro_paste! {
#[doc = "Create a new `" $ret "` object."]
pub fn new() -> $ret { todo!() }
}
};
}
pub struct macro_paste {}
method_new!(macro_paste); // expands to #[doc = "Create a new `macro_paste` object"]
```
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>
## Star History
[](https://www.star-history.com/#butlergroup/macro_paste&Date)