hpl_attribute_event/
lib.rs1extern 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 }
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 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 #func_stream
113
114 }
115 }
116 })
117}