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