From f507084eafc41875003f0ca9351fc0ee93f50f64 Mon Sep 17 00:00:00 2001 From: ngundotra Date: Wed, 3 May 2023 12:17:53 -0400 Subject: [PATCH] explicitly only parse two args --- lang/attribute/event/src/lib.rs | 42 ++++++++++++++++++------- tests/events/programs/events/src/lib.rs | 6 ++-- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/lang/attribute/event/src/lib.rs b/lang/attribute/event/src/lib.rs index 68f7e8c46c..573576d97f 100644 --- a/lang/attribute/event/src/lib.rs +++ b/lang/attribute/event/src/lib.rs @@ -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 @@ -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 { + let arg1: Expr = input.parse()?; + input.parse::()?; + 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 = anchor_lang::Event::data(&#second); + let __inner_data: Vec = anchor_lang::Event::data(&#event_struct); let __ix_data: Vec = __disc.into_iter().chain(__inner_data.into_iter()).collect(); let __ix = anchor_lang::solana_program::instruction::Instruction::new_with_bytes( diff --git a/tests/events/programs/events/src/lib.rs b/tests/events/programs/events/src/lib.rs index 1dac02b881..7d0fffc777 100644 --- a/tests/events/programs/events/src/lib.rs +++ b/tests/events/programs/events/src/lib.rs @@ -25,13 +25,13 @@ pub mod events { } pub fn test_event_cpi(ctx: Context) -> Result<()> { - emit_cpi!(( + emit_cpi!( ctx.accounts.program.to_account_info(), MyOtherEvent { data: 7, label: "cpi".to_string(), - }, - )); + } + ); Ok(()) } }