macro_rules! split_generics_and_where {
( $($args:tt)* ) => { ... };
}
Available on crate feature
generics_parsing
only.Expand description
For parsing item definitions, passing the generic parameters unchanged to a callback macro.
Examples
Basic
Basic example of using this macro, and what it passes to a callback macro.
For a more realistic example you can look at the one below
use core_extensions::split_generics_and_where;
assert_eq!(hello(), "world");
// `split_generics_and_where` calls `crate::foo` here
split_generics_and_where! {
crate::foo!{
// The first tokens passed to the `crate::foo` macro
hello "world" foo bar
}
(
// The parsed tokens
<'a, T: Foo, const N: usize> (param: Type) -> u32
where
T: Bar,
{ println }
)
}
#[macro_export]
macro_rules! foo {
(
$fn_name:ident $string:literal foo bar
('a, T: Foo, const N: usize) // the generic parameters
((param: Type) -> u32 ) // before the where clause
(T: Bar,) // inside the where clause
( { println } ) // after the where clause
) => {
fn $fn_name() -> &'static str {
$string
}
};
}
Parsing a function
This demonstrates how you can parse a function.
use std::ops::Mul;
crate::inject_increment! {
pub fn square(x: u32) -> u32 {
x * x
}
}
crate::inject_increment! {
pub(crate) unsafe fn cube<T>(x: T) -> T
where
T: Mul<Output = T> + Copy
{
x * x * x
}
}
fn main() {
assert_eq!(get_count(), 0);
assert_eq!(square(3), 9);
assert_eq!(get_count(), 1);
assert_eq!(unsafe{ cube(5) }, 125);
assert_eq!(get_count(), 2);
}
#[macro_export]
macro_rules! inject_increment {
(
$(#[$attr:meta])*
$vis:vis
$(unsafe $(@$unsafe:tt@)?)?
fn $name:ident $($rem:tt)*
) => {
$crate::__::split_generics_and_where!{
$crate::__priv_inject_increment! {
$(#[$attr])*
$vis,
($(unsafe $(@$unsafe@)?)?)
fn $name
}
($($rem)*)
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __priv_inject_increment{
(
$(#[$attr:meta])*
$vis:vis,
($($unsafe:tt)?)
fn $name:ident
( $($generics:tt)* )
( ($($fn_params:tt)*) $( -> $ret_ty:ty )? )
( $($where_preds:tt)* )
( { $($code:tt)* } )
) => {
$(#[$attr])*
$vis
$($unsafe)?
fn $name< $($generics)* > ( $($fn_params)* ) $( -> $ret_ty )?
where $($where_preds)*
{
$crate::increment_count();
$($code)*
}
}
}
#[doc(hidden)]
pub mod __ {
pub use core_extensions::split_generics_and_where;
}
use std::sync::atomic::{AtomicU64, Ordering as AtomOrd};
pub static COUNT: AtomicU64 = AtomicU64::new(0);
fn increment_count() {
COUNT.fetch_add(1, AtomOrd::Relaxed);
}
fn get_count() -> u64 {
COUNT.load(AtomOrd::Relaxed)
}