use proc_macro::TokenStream;
use quote::quote;
use serde_json::Value;
use std::path::PathBuf;
use syn::parse::{Parse, ParseStream};
use syn::{Ident, LitStr, Token, parse_macro_input};
struct LoadAbiArgs {
ident: Ident,
_comma: Token![,],
file_path: LitStr,
}
impl Parse for LoadAbiArgs {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
Ok(LoadAbiArgs {
ident: input.parse()?,
_comma: input.parse()?,
file_path: input.parse()?,
})
}
}
pub fn load_abi(input: TokenStream) -> TokenStream {
let LoadAbiArgs {
ident, file_path, ..
} = parse_macro_input!(input as LoadAbiArgs);
let file_path = file_path.value();
let crate_root = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
let absolute_path = PathBuf::from(crate_root).join(file_path.clone());
if !absolute_path.exists() {
return syn::Error::new_spanned(
file_path,
format!("ABI file not found at: {}", absolute_path.display()),
)
.to_compile_error()
.into();
}
let file_content = std::fs::read_to_string(&absolute_path).expect("Failed to read ABI file");
let json: Value = serde_json::from_str(&file_content).expect("Failed to parse JSON");
let abi = json["abi"].to_string();
quote! {
const #ident: &str = #abi;
}
.into()
}