magic_params/
lib.rs

1pub use paste;
2pub use seq_macro;
3
4#[macro_export]
5macro_rules! define_context {
6    ($ctx: ident {
7        $($field: ident : $type: ty),* $(,)?
8    }) => {
9        pub struct $ctx {
10            $(pub $field: $type),*
11        }
12
13        $crate::paste::paste! {
14            pub trait [< From $ctx >] {
15                fn from_context(ctx: &$ctx) -> Self;
16            }
17
18            $(
19                impl [< From $ctx >] for $type {
20                    fn from_context(ctx: &$ctx) -> Self {
21                        ctx.$field.clone()
22                    }
23                }
24            )*
25        }
26    };
27}
28
29#[macro_export]
30macro_rules! context_as_params {
31    (impl $ctx: ident, $max: expr) => {
32        $crate::seq_macro::seq!(N in 1..=$max {
33            $crate::paste::paste! {
34                impl<F, #(T~N,)* O> [< $ctx Handler >]<(#(T~N,)*), O> for F
35                where
36                    F: Fn(#(T~N,)*) -> O,
37                    #(T~N: [< From $ctx >],)*
38                {
39                    fn call(self, ctx: &$ctx) -> O {
40                        (self)(#(T~N::from_context(&ctx),)*)
41                    }
42                }
43            }
44        });
45
46    };
47
48    ($ctx: ident, $max: expr) => {
49        $crate::paste::paste! {
50            trait [< $ctx Handler >]<T, O> {
51                fn call(self, ctx: &$ctx) -> O;
52            }
53        }
54        $crate::seq_macro::seq!(N in 1..=$max {
55            context_as_params!(impl $ctx, N);
56        });
57    };
58
59    ($ctx: ident) => {
60        context_as_params!($ctx, 6);
61    };
62}