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}