zink_codegen/
selector.rs

1//! Macro for the function selector.
2
3use proc_macro::TokenStream;
4use proc_macro2::{Ident, Span};
5use quote::quote;
6use syn::{parse_quote, ItemFn};
7use zabi::Abi;
8
9/// Mark the function as external.
10pub fn external(mut item: ItemFn) -> TokenStream {
11    item.sig.abi = Some(parse_quote! { extern "C" });
12    item.attrs.push(parse_quote! { #[no_mangle] });
13    item.attrs
14        .push(parse_quote! { #[allow(improper_ctypes_definitions)] });
15
16    let selector: ItemFn = {
17        let func = item.sig.ident.clone().to_string();
18        let ident = Ident::new(&(func.clone() + "_selector"), Span::call_site());
19        let abi = Abi::from(&item.sig).to_hex().expect("ABI is not supported");
20        let abi_len = abi.len() as u32;
21        let doc = " EVM selector for the function `".to_string() + &func + "`";
22
23        parse_quote! {
24            #[no_mangle]
25            #[cfg(target_arch = "wasm32")]
26            #[doc = #doc]
27            pub extern "C" fn #ident() {
28                unsafe {
29                    zink::ffi::emit_abi(#abi.as_ptr() as u32, #abi_len);
30                }
31            }
32        }
33    };
34
35    quote! {
36        #item
37
38        #selector
39    }
40    .into()
41}