Macro core_extensions::split_generics_and_where[][src]

macro_rules! split_generics_and_where {
    (
        $(:: $(@$leading:tt@)? )? $first:ident $(:: $trailing:ident)* ! $prefix:tt
        ($($generics:tt)*)
    ) => { ... };
}
This is supported on crate feature generics_parsing only.

For parsing item definitions, passing the generic parameters unchanged to a callback macro.

Version compatibility

This macro can only be used inside of functions since Rust 1.45.0, before that version it can only be used outside of functions.

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;
 
fn main() {
    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 core_extensions::split_generics_and_where;
 
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)*
    ) => {
        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)* 
        }
    }
}
 
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)
}