hpl_attribute_event/
lib.rs

1extern crate proc_macro2;
2
3use convert_case::{Case, Casing};
4use quote::quote;
5use syn::{parse_macro_input, Fields};
6
7#[proc_macro_attribute]
8pub fn event(
9    _args: proc_macro::TokenStream,
10    input: proc_macro::TokenStream,
11) -> proc_macro::TokenStream {
12    let mut event_enum = parse_macro_input!(input as syn::ItemEnum);
13    let event_name = &event_enum.ident;
14
15    if event_enum.generics.params.len() > 0 {
16        panic!("HPL Events does not allow generics");
17    }
18
19    let mut func_stream = proc_macro2::TokenStream::default();
20    event_enum.variants.iter_mut().for_each(|variant| {
21        let name = &variant.ident;
22        let formated_name = name
23            .to_string()
24            .to_case(Case::Snake)
25            .parse::<proc_macro2::TokenStream>()
26            .unwrap();
27        let mut new_variant: syn::Variant = syn::parse(proc_macro::TokenStream::from({
28            quote! {
29                #name {
30                    timestamp: i64
31                    // name: u8
32                }
33            }
34        }))
35        .unwrap();
36        let mut func_args_stream = proc_macro2::TokenStream::default();
37        let mut func_fields_stream = proc_macro2::TokenStream::default();
38        if let Fields::Named(fileds) = &mut variant.fields {
39            if let Fields::Named(new_fields) = &mut new_variant.fields {
40                fileds.named.iter().for_each(|f| {
41                    if let Some(field_name) = &f.ident {
42                        // if let () = f.ty {}
43                        let ty = &f.ty;
44                        func_args_stream.extend::<proc_macro2::TokenStream>(quote! {
45                            #field_name: #ty,
46                        });
47                        func_fields_stream.extend::<proc_macro2::TokenStream>(quote! {
48                            #field_name,
49                        });
50                    }
51                    new_fields.named.push(f.clone())
52                });
53            }
54        }
55        variant.fields = new_variant.fields;
56        func_stream.extend::<proc_macro2::TokenStream>(quote! {
57            pub fn #formated_name(#func_args_stream clock: &Clock) -> Self {
58                #event_name::#name {
59                    #func_fields_stream
60                    timestamp: clock.unix_timestamp
61                }
62            }
63        });
64    });
65
66    proc_macro::TokenStream::from({
67        quote! {
68            #[derive(borsh::BorshSerialize, borsh::BorshDeserialize)]
69            #event_enum
70
71            #[automatically_derived]
72            impl #event_name {
73
74                pub fn wrap(&self) -> Vec<u8> {
75                    vec![
76                        crate::id().try_to_vec().unwrap(),
77                        self.try_to_vec().unwrap(),
78                    ].concat()
79                }
80
81                pub fn emit<'info>(&self, noop: &Program<'info, Noop>) -> Result<()> {
82                    wrap_application_data_v1(
83                        self.wrap(),
84                        noop,
85                    )
86                }
87
88                // pub fn to_instruction(&self, wrapper_program_id: Pubkey) -> Instruction {
89                //     Instruction {
90                //         program_id: wrapper_program_id,
91                //         accounts: vec![],
92                //         data: self.wrap(),
93                //     }
94                // }
95
96                // pub fn emit_to<'info>(&self, wrapper_program: AccountInfo<'info>) -> ProgramResult {
97                //     invoke(
98                //         &self.to_instruction(wrapper_program.key()),
99                //         &[wrapper_program],
100                //     )
101                // }
102
103                // pub fn emit<'info>(&self, hpl_events_program: AccountInfo<'info>) -> ProgramResult {
104                //     if String::from("EventNxhSA3AcXD14PmXaYUiNQWwoKbLeGHtwydixRzX")
105                //         != hpl_events_program.key.to_string()
106                //     {
107                //         return Err(ProgramError::IncorrectProgramId);
108                //     };
109                //     self.emit_to(hpl_events_program)
110                // }
111
112                #func_stream
113
114            }
115        }
116    })
117}