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}