ethbind_rust_macros/
lib.rs1use std::{env, fs::read_to_string, path::PathBuf};
2
3use ethbind_rust::{BindingBuilder, JsonRuntimeBinder, RustGenerator, ToTokenStream};
4use proc_macro::TokenStream;
5use proc_macro2::Ident;
6use quote::quote;
7use syn::{parse::Parse, parse_macro_input, LitStr, Token};
8
9struct Contract {
10 pub contract_name: Option<String>,
11 pub type_mapping: String,
12 pub abi_data: String,
13}
14
15impl Parse for Contract {
16 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
17 let contract_name: Option<Ident> = input.parse()?;
18
19 if contract_name.is_some() {
20 input.parse::<Token!(,)>()?;
21 }
22
23 let type_mapping: LitStr = input.parse()?;
24
25 input.parse::<Token!(,)>()?;
26
27 let abi_data: LitStr = input.parse()?;
28
29 Ok(Self {
30 contract_name: contract_name.map(|c| c.to_string()),
31 type_mapping: type_mapping.value(),
32 abi_data: abi_data.value(),
33 })
34 }
35}
36
37mod contract {
38 syn::custom_keyword!(hardhat);
39}
40
41fn load_json_file(path: &str) -> String {
42 let dir = env::var("CARGO_MANIFEST_DIR").expect("Find CARGO_MANIFEST_DIR");
43
44 let path = PathBuf::from(dir).join(path);
45
46 read_to_string(path.clone()).expect(&format!("Read json file: {:?}", path))
47}
48
49#[proc_macro]
50pub fn contract(item: TokenStream) -> TokenStream {
51 let contract = parse_macro_input!(item as Contract);
52
53 let type_mapping: JsonRuntimeBinder = load_json_file(&contract.type_mapping)
54 .parse()
55 .expect("Parse mapping data");
56
57 let abi_data = load_json_file(&contract.abi_data);
58
59 let generator = if let Some(contract_name) = contract.contract_name {
60 BindingBuilder::new((RustGenerator::default(), type_mapping))
61 .bind(&contract_name, abi_data)
62 .finalize()
63 .expect("Generate contract/abi binding code")
64 } else {
65 BindingBuilder::new((RustGenerator::default(), type_mapping))
66 .bind_hardhat(abi_data)
67 .finalize()
68 .expect("Generate contract/abi binding code")
69 };
70
71 let contracts = generator.to_token_streams().expect("To token streams");
72
73 quote!(#(#contracts)*).into()
74}