specialize_call

Macro specialize_call 

Source
macro_rules! specialize_call {
    (@single_mapping,
        ( $($acc_p:pat),* ),
        ( $($acc_t:ty),* ),
        $func:tt, $args:tt, $select:tt,
        [ ($p:pat => $($t:ty),+ ) $(, $p_t:tt)* $(,)* ],
        $mappings:tt
    ) => { ... };
    (@single_mapping,
        $acc_p:tt, $acc_t: tt,
        $func:tt, $args:tt, $select:tt,
        [],
        $mappings:tt
    ) => { ... };
    (@specialize_call,
        $acc_p:tt,
        $acc_t:tt,
        $func:tt,
        $args:tt,
        $select:tt,

        ($head:tt $(, $tail:tt)*)
    ) => { ... };
    (@specialize_call,
        $acc_p:tt,
        $acc_t:tt,
        $func:tt,
        $args:tt,
        $select:tt,

        ()
    ) => { ... };
    (@maybe_invoke,
        ( $($acc_p:pat),* ),
        ( $($acc_t:ty),* ),
        $select:expr,
        $func:ident,
        ($($arg:expr),*)
    ) => { ... };
    ($func:ident, ($($arg:expr),* $(,)*), $select:expr, $($mapping:tt),+ $(,)*) => { ... };
}
Expand description

A macro producing the invocations of the specified generic function with specific types, depending on the value available in runtime.

Examples:

 
struct A<const I: usize>();
struct B<const I: usize>();
struct C<const I: usize>();
 
#[derive(Debug)]
enum Select<const I: usize> {
    A,
    B,
    C,
}
 
use core::any::type_name as tn;
 
#[test]
fn specialize_call_1() {
    // there is a function `do_it` that takes one runtime argument, and one type-parameter.
    fn do_it<T>(_arg: usize) -> &'static str {
        tn::<T>()
    }
 
    assert_eq!(
        specialize_call!(
            // invoke `do_it::<?>`
            do_it, 
            // use `(1)` as the arguments list
            (1), 
            // choose the type-parameter depending on this value
            Select::<1>::A, 
            // the choice map
            [
                // if the provided value is `Select::A`, then invoke `do_it::<A>`
                (Select::<1>::A => A::<1>),
                // if the provided value is `Select::B`, then invoke `do_it::<B>`
                (Select::<1>::B => B::<1>),
            ]),
        Some(tn::<A<1>>())
    );
 
    assert_eq!(
        specialize_call!(do_it, (2), Select::<1>::B, [
                (Select::<1>::A => A::<1>),
                (Select::<1>::B => B::<1>),
            ]),
        Some(tn::<B<1>>()),
    );
 
    assert_eq!(
        specialize_call!(do_it, (3), Select::<1>::C, [
                (Select::<1>::A => A::<1>),
                (Select::<1>::B => B::<1>),
            ]),
        None::<&str>,
    );
}