zink_codegen/
selector.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//! Macro for the function selector.

use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::quote;
use syn::{parse_quote, ItemFn};
use zabi::Abi;

/// Mark the function as external.
pub fn external(mut item: ItemFn) -> TokenStream {
    item.sig.abi = Some(parse_quote! { extern "C" });
    item.attrs.push(parse_quote! { #[no_mangle] });
    item.attrs
        .push(parse_quote! { #[allow(improper_ctypes_definitions)] });

    let selector: ItemFn = {
        let func = item.sig.ident.clone().to_string();
        let ident = Ident::new(&(func.clone() + "_selector"), Span::call_site());
        let abi = Abi::from(&item.sig).to_hex().expect("ABI is not supported");
        let abi_len = abi.len() as u32;
        let doc = " EVM selector for the function `".to_string() + &func + "`";

        parse_quote! {
            #[no_mangle]
            #[cfg(target_arch = "wasm32")]
            #[doc = #doc]
            pub extern "C" fn #ident() {
                unsafe {
                    zink::ffi::emit_abi(#abi.as_ptr() as u32, #abi_len);
                }
            }
        }
    };

    quote! {
        #item

        #selector
    }
    .into()
}