extern crate proc_macro; use quote::quote; use syn::parse_macro_input; /// The event attribute allows a struct to be used with /// [emit!](./macro.emit.html) so that programs can log significant events in /// their programs that clients can subscribe to. Currently, this macro is for /// structs only. #[proc_macro_attribute] pub fn event( _args: proc_macro::TokenStream, input: proc_macro::TokenStream, ) -> proc_macro::TokenStream { let event_strct = parse_macro_input!(input as syn::ItemStruct); let event_name = &event_strct.ident; let discriminator: proc_macro2::TokenStream = { let discriminator_preimage = format!("event:{}", event_name.to_string()); let mut discriminator = [0u8; 8]; discriminator.copy_from_slice( &anchor_syn::hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..8], ); format!("{:?}", discriminator).parse().unwrap() }; proc_macro::TokenStream::from(quote! { #[derive(anchor_lang::__private::EventIndex, AnchorSerialize, AnchorDeserialize)] #event_strct impl anchor_lang::Event for #event_name { fn data(&self) -> Vec { let mut d = #discriminator.to_vec(); d.append(&mut self.try_to_vec().unwrap()); d } } impl anchor_lang::Discriminator for #event_name { fn discriminator() -> [u8; 8] { #discriminator } } }) } /// Creates an event that can be subscribed to by clients. Calling this method /// will internally borsh serialize the [event](./attr.event.html), base64 /// encode the bytes, and then add a [msg!](../solana_program/macro.msg.html) /// log to the transaction. #[proc_macro] pub fn emit(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let data: proc_macro2::TokenStream = input.into(); proc_macro::TokenStream::from(quote! { { let data = anchor_lang::Event::data(&#data); let msg_str = &anchor_lang::__private::base64::encode(data); anchor_lang::solana_program::msg!(msg_str); } }) } // EventIndex is a marker macro. It functionally does nothing other than // allow one to mark fields with the `#[index]` inert attribute, which is // used to add metadata to IDLs. #[proc_macro_derive(EventIndex, attributes(index))] pub fn derive_event(_item: proc_macro::TokenStream) -> proc_macro::TokenStream { proc_macro::TokenStream::from(quote! {}) }