extern crate proc_macro;
use quote::quote;
use syn::parse_macro_input;
use syn::{parse::Parse, Expr, Token};
struct MacroInput2 {
arg_1: Expr,
comma: Token![,],
arg_2: Expr,
}
impl Parse for MacroInput2 {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Self {
arg_1: input.parse()?,
comma: input.parse()?,
arg_2: input.parse()?,
})
}
}
#[proc_macro_derive(SchemaGeneratorAnchor)]
pub fn schema_generator_anchor(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let account_strct = parse_macro_input!(input as syn::ItemStruct);
let account_name = &account_strct.ident;
proc_macro::TokenStream::from(quote! {
impl solalumin_state::states::SchemaEventAnchor for #account_name {
fn generate_schema(self) -> Vec<u8> {
let mut d = Self::DISCRIMINATOR.to_vec();
let mut defs = Default::default();
Self::add_definitions_recursively(&mut defs);
let container: borsh::schema::BorshSchemaContainer = Self::schema_container();
let mut data = container
.try_to_vec()
.expect("Failed to serialize BorshSchemaContainer for account");
d.append(&mut data);
d
}
}
})
}
#[proc_macro_attribute]
pub fn schema_generator(
_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}");
let mut discriminator = [0u8; 8];
discriminator.copy_from_slice(
&solalumin_state::solalumin_hash::hash(discriminator_preimage.as_bytes()).to_bytes()[..8],
);
format!("{discriminator:?}").parse().unwrap()
};
proc_macro::TokenStream::from(quote! {
#[derive(borsh::BorshSerialize, borsh::BorshDeserialize, borsh::BorshSchema)]
#event_strct
impl solalumin_state::states::SchemaEvent for #event_name {
fn data(&self) -> Vec<u8> {
let mut d = #discriminator.to_vec();
d.append(&mut self.try_to_vec().unwrap());
d
}
fn generate_schema(self) -> Vec<u8> {
let mut d = #discriminator.to_vec();
let mut defs = Default::default();
Self::add_definitions_recursively(&mut defs);
let container: borsh::schema::BorshSchemaContainer = Self::schema_container();
let mut data = container
.try_to_vec()
.expect("Failed to serialize BorshSchemaContainer for event");
d.append(&mut data);
d
}
}
impl solalumin_state::states::Discriminator for #event_name {
const DISCRIMINATOR: [u8; 8] = #discriminator;
}
})
}
#[proc_macro]
pub fn register_program_log_data_schema(
token_stream: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input = parse_macro_input!(token_stream as MacroInput2);
let data = &input.arg_1;
let is_anchor = &input.arg_2;
proc_macro::TokenStream::from(quote! {
{
let schema_string = base64::encode(#data.generate_schema().as_slice());
msg!("LD:{}:{}", #is_anchor, schema_string);
}
})
}
#[proc_macro]
pub fn register_program_account_schema(
token_stream: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input = parse_macro_input!(token_stream as MacroInput2);
let data = &input.arg_1;
let is_anchor = &input.arg_2;
proc_macro::TokenStream::from(quote! {
{
let schema_string = base64::encode(#data.generate_schema().as_slice());
msg!("AR:{}:{}", #is_anchor, schema_string);
}
})
}
#[proc_macro]
pub fn register_program_instruction_log_schema(
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let data: proc_macro2::TokenStream = input.into();
proc_macro::TokenStream::from(quote! {
{
solana_program::log::sol_log_data(&[&#data.generate_schema()]);
}
})
}
#[proc_macro]
pub fn publish(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let data: proc_macro2::TokenStream = input.into();
proc_macro::TokenStream::from(quote! {
{
solana_program::log::sol_log_data(&[&solalumin_state::states::SchemaEvent::data(&#data)]);
}
})
}