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)
}