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