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            
15            pub trait [< From $ctx >]<'a> {
16                fn from_context(ctx: &'a $ctx) -> Self;
17            }
18            
19
20            $(
21                impl<'a> [< From $ctx >]<'a> for &'a $type {
22                    fn from_context(ctx: &'a $ctx) -> Self {
23                        &ctx.$field
24                    }
25                }
26
27                impl [< From $ctx >]<'_> for $type where for<'a> $type: Clone {
28                    fn from_context(ctx: &$ctx) -> Self {
29                        ctx.$field.clone()
30                    }
31                }
32            )*
33
34        }
35    };
36}
37
38#[macro_export]
39macro_rules! context_as_params {
40    (impl $ctx: ident, $max: expr) => {
41        $crate::seq_macro::seq!(N in 1..=$max {
42            $crate::paste::paste! {
43                impl<'a, F, #(T~N,)* O> [< $ctx Handler >]<'a, (#(T~N,)*), O> for F
44                where
45                    F: Fn(#(T~N,)*) -> O,
46                    #(T~N: [< From $ctx >]<'a>,)*
47                {
48                    fn call(self, ctx: &'a $ctx) -> O {
49                        (self)(#(T~N::from_context(&ctx),)*)
50                    }
51                }
52            }
53        });
54
55    };
56
57    ($ctx: ident, $max: expr) => {
58        $crate::paste::paste! {
59            pub trait [< $ctx Handler >]<'a, T, O> {
60                fn call(self, ctx: &'a $ctx) -> O;
61            }
62        }
63        $crate::seq_macro::seq!(N in 1..=$max {
64            $crate::context_as_params!(impl $ctx, N);
65        });
66    };
67
68    ($ctx: ident) => {
69        $crate::context_as_params!($ctx, 6);
70    };
71}