typhoon_context/
lib.rs

1use paste::paste;
2
3mod args;
4mod remaining_accounts;
5
6pub use args::*;
7use {pinocchio::account_info::AccountInfo, typhoon_errors::Error};
8
9pub trait HandlerContext<'a>: Sized {
10    fn from_entrypoint(
11        accounts: &mut &'a [AccountInfo],
12        instruction_data: &mut &'a [u8],
13    ) -> Result<Self, Error>;
14}
15
16pub trait Handler<'a, T> {
17    type Output;
18
19    fn call(
20        self,
21        accounts: &mut &'a [AccountInfo],
22        instruction_data: &mut &'a [u8],
23    ) -> Result<Self::Output, Error>;
24}
25
26impl<'a, F, O> Handler<'a, ()> for F
27where
28    F: FnOnce() -> Result<O, Error>,
29{
30    type Output = O;
31
32    fn call(
33        self,
34        _accounts: &mut &'a [AccountInfo],
35        _instruction_data: &mut &'a [u8],
36    ) -> Result<Self::Output, Error> {
37        (self)()
38    }
39}
40
41macro_rules! impl_handler {
42    ($( $t:ident ),+) => {
43        impl<'a, $( $t, )* F, O> Handler<'a, ($( $t, )*)> for F
44        where
45            F: FnOnce($( $t ),*) -> Result<O, Error>,
46            $(
47                $t: HandlerContext<'a>,
48            )*
49        {
50            type Output = O;
51
52            fn call(
53                self,
54                accounts: &mut &'a [AccountInfo],
55                instruction_data: &mut &'a [u8],
56            ) -> Result<Self::Output, Error> {
57                paste! {
58                    $(
59                        let [<$t:lower>] = $t::from_entrypoint(accounts, instruction_data)?;
60                    )*
61                    (self)($( [<$t:lower>], )*)
62                }
63            }
64        }
65    };
66}
67
68impl_handler!(T1);
69impl_handler!(T1, T2);
70impl_handler!(T1, T2, T3);
71impl_handler!(T1, T2, T3, T4);
72impl_handler!(T1, T2, T3, T4, T5);
73impl_handler!(T1, T2, T3, T4, T5, T6);
74impl_handler!(T1, T2, T3, T4, T5, T6, T7);
75
76pub fn handle<'a, T, H>(
77    mut accounts: &'a [AccountInfo],
78    mut instruction_data: &'a [u8],
79    handler: H,
80) -> Result<H::Output, Error>
81where
82    H: Handler<'a, T>,
83{
84    handler.call(&mut accounts, &mut instruction_data)
85}