typhoon_context/
lib.rs

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}