Skip to content

Commit

Permalink
lang: Add Event utility type to get events from bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
acheroncrypto committed Apr 9, 2024
1 parent c7ccbb8 commit 93c0e7c
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 1 deletion.
7 changes: 6 additions & 1 deletion lang/attribute/program/src/declare_program/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use common::gen_docs;
use mods::{
accounts::gen_accounts_mod, client::gen_client_mod, constants::gen_constants_mod,
cpi::gen_cpi_mod, events::gen_events_mod, internal::gen_internal_mod, program::gen_program_mod,
types::gen_types_mod,
types::gen_types_mod, utils::gen_utils_mod,
};

pub struct DeclareProgram {
Expand Down Expand Up @@ -66,6 +66,9 @@ fn gen_program(idl: &Idl, name: &syn::Ident) -> proc_macro2::TokenStream {
let client_mod = gen_client_mod(idl);
let internal_mod = gen_internal_mod(idl);

// Utils
let utils_mod = gen_utils_mod(idl);

quote! {
#docs
pub mod #name {
Expand All @@ -82,6 +85,8 @@ fn gen_program(idl: &Idl, name: &syn::Ident) -> proc_macro2::TokenStream {
#cpi_mod
#client_mod
#internal_mod

#utils_mod
}
}
}
Expand Down
1 change: 1 addition & 0 deletions lang/attribute/program/src/declare_program/mods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ pub mod events;
pub mod internal;
pub mod program;
pub mod types;
pub mod utils;

use super::common;
61 changes: 61 additions & 0 deletions lang/attribute/program/src/declare_program/mods/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use anchor_idl::types::Idl;
use quote::{format_ident, quote};

use super::common::gen_discriminator;

pub fn gen_utils_mod(idl: &Idl) -> proc_macro2::TokenStream {
let event = gen_event(idl);

quote! {
/// Program utilities.
pub mod utils {
#event
}
}
}

fn gen_event(idl: &Idl) -> proc_macro2::TokenStream {
let variants = idl
.events
.iter()
.map(|ev| format_ident!("{}", ev.name))
.map(|name| quote! { #name(#name) });
let match_arms = idl.events.iter().map(|ev| {
let disc = gen_discriminator(&ev.discriminator);
let name = format_ident!("{}", ev.name);
let event = quote! { #name::try_from_slice(value).map(Self::#name) };
quote! { #disc => #event }
});

quote! {
use super::{*, events::*};

/// An enum that includes all events of the declared program as a tuple variant.
///
/// See [`Self::try_from_bytes`] to create an instance from bytes.
pub enum Event {
#(#variants,)*
}

impl Event {
/// Try to create an event based on the given bytes.
///
/// This method returns an error if the discriminator of the given bytes don't match
/// with any of the existing events, or if the deserialization fails.
pub fn try_from_bytes(bytes: &[u8]) -> std::io::Result<Self> {
Self::try_from(bytes)
}
}

impl TryFrom<&[u8]> for Event {
type Error = std::io::Error;

fn try_from(value: &[u8]) -> std::io::Result<Self> {
match &value[..8] {
#(#match_arms,)*
_ => Err(std::io::ErrorKind::NotFound.into()),
}
}
}
}
}

0 comments on commit 93c0e7c

Please sign in to comment.