continuation_router_syn/
lib.rs1#![allow(clippy::needless_return)]
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::{parse_macro_input, AttributeArgs, DeriveInput, Ident, Meta, NestedMeta};
5
6#[proc_macro_attribute]
7pub fn router_action(args: TokenStream, input: TokenStream) -> TokenStream {
8 let args = parse_macro_input!(args as AttributeArgs);
9 let mut ast = parse_macro_input!(input as DeriveInput);
10 match &mut ast.data {
11 syn::Data::Struct(ref mut _struct_data) => {
12 let name = &ast.ident;
14 let action_name = &Ident::new(format!("{}", name).as_str(), name.span());
15
16 let process_impl = match &*args {
17 [NestedMeta::Meta(Meta::Path(path))]
18 if path
19 .clone()
20 .segments
21 .into_iter()
22 .any(|s| s.ident == "pass_through") =>
23 {
24 quote! {
25 impl<'info> crate::processor::ActionInputOutput<'info> for ActionContext<'_, '_, '_, 'info, #action_name<'info>> {
26 fn input_account(&self) -> &Account<'info, TokenAccount> {
27 &self.action.input
28 }
29
30 fn output_account(&self) -> &Account<'info, TokenAccount> {
31 &self.action.output
32 }
33 }
34
35 impl<'info> crate::processor::Processor<'info> for ActionContext<'_, '_, '_, 'info, #action_name<'info>> {
36 fn process_unchecked(
37 &self,
38 amount_in: u64,
39 minimum_amount_out: u64
40 ) -> Result<()> {
41 crate::router_action_processor::process_action(
42 CpiContext::new(
43 self.swap_program.clone(),
44 self.remaining_accounts.to_vec()
45 ),
46 Self::TYPE.into(),
47 amount_in,
48 minimum_amount_out,
49 )
50 }
51 }
52 }
53 }
54 _ => quote! {
55 impl<'info> crate::processor::ActionInputOutput<'info> for ActionContext<'_, '_, '_, 'info, #action_name<'info>> {
56 fn input_account(&self) -> &Account<'info, TokenAccount> {
57 self.action.input_account()
58 }
59 fn output_account(&self) -> &Account<'info, TokenAccount> {
60 self.action.output_account()
61 }
62 }
63
64 impl<'info> crate::processor::Processor<'info> for ActionContext<'_, '_, '_, 'info, #action_name<'info>> {
65 fn process_unchecked(
66 &self,
67 amount_in: u64,
68 minimum_amount_out: u64
69 ) -> Result<()> {
70 ProcessAction::process(self, amount_in, minimum_amount_out)
71 }
72 }
73 },
74 };
75
76 ast.ident = action_name.clone();
77
78 return quote! {
79 #ast
82
83 #process_impl
91
92 impl<'info> crate::Action for ActionContext<'_, '_, '_, '_, #action_name<'info>> {
93 const TYPE: crate::ActionType = crate::ActionType::#action_name;
94 }
95 }
96 .into();
97 }
98 _ => panic!("`add_field` has to be used with structs "),
99 }
100}