Skip to content

Commit

Permalink
explicitly only parse two args
Browse files Browse the repository at this point in the history
  • Loading branch information
ngundotra committed May 3, 2023
1 parent 7bc2c25 commit f507084
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 14 deletions.
42 changes: 31 additions & 11 deletions lang/attribute/event/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
extern crate proc_macro;

use quote::quote;
use syn::parse_macro_input;
use syn::{
parse::{Parse, ParseStream},
parse_macro_input, Expr, Token,
};

/// The event attribute allows a struct to be used with
/// [emit!](./macro.emit.html) so that programs can log significant events in
Expand Down Expand Up @@ -81,23 +84,40 @@ pub fn emit(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
})
}

#[proc_macro]
pub fn emit_cpi(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let tuple = parse_macro_input!(input as syn::ExprTuple);
// Custom wrapper struct (thanks ChatGPT!)
struct TwoArgs {
arg1: Expr,
arg2: Expr,
}

// Implement the `Parse` trait for the `TwoArgs` struct
impl Parse for TwoArgs {
fn parse(input: ParseStream) -> syn::Result<Self> {
let arg1: Expr = input.parse()?;
input.parse::<Token![,]>()?;
let arg2: Expr = input.parse()?;

if !input.is_empty() {
return Err(input.error("Expected exactly 2 arguments"));
}

let elems = tuple.elems;
if elems.len() != 2 {
panic!("Expected a tuple with exactly two elements.");
Ok(TwoArgs { arg1, arg2 })
}
}

#[proc_macro]
pub fn emit_cpi(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
// let tuple = parse_macro_input!(input as syn::ExprTuple);
let two_args = parse_macro_input!(input as TwoArgs);

let first = &elems[0];
let second = &elems[1];
let self_program_info = &two_args.arg1;
let event_struct = &two_args.arg2;

proc_macro::TokenStream::from(quote! {
let program_info: anchor_lang::solana_program::account_info::AccountInfo = #first;
let program_info: anchor_lang::solana_program::account_info::AccountInfo = #self_program_info;

let __disc = crate::event::EVENT_IX_TAG_LE;
let __inner_data: Vec<u8> = anchor_lang::Event::data(&#second);
let __inner_data: Vec<u8> = anchor_lang::Event::data(&#event_struct);
let __ix_data: Vec<u8> = __disc.into_iter().chain(__inner_data.into_iter()).collect();

let __ix = anchor_lang::solana_program::instruction::Instruction::new_with_bytes(
Expand Down
6 changes: 3 additions & 3 deletions tests/events/programs/events/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ pub mod events {
}

pub fn test_event_cpi(ctx: Context<TestEventCpi>) -> Result<()> {
emit_cpi!((
emit_cpi!(
ctx.accounts.program.to_account_info(),
MyOtherEvent {
data: 7,
label: "cpi".to_string(),
},
));
}
);
Ok(())
}
}
Expand Down

0 comments on commit f507084

Please sign in to comment.