calimero_wasm_abi/
embed.rs

1use serde_json;
2
3use crate::schema::Manifest;
4
5/// Embed the ABI manifest into the WASM binary as a custom section
6/// This macro generates the custom section and exports the get_abi* functions
7#[macro_export]
8macro_rules! embed_abi {
9    ($manifest:expr) => {
10        // Serialize the manifest to JSON
11        const ABI_JSON: &str = $manifest;
12
13        // Create the custom section with the ABI JSON
14        #[cfg_attr(target_os = "macos", link_section = "__DATA,calimero_abi_v1")]
15        #[cfg_attr(not(target_os = "macos"), link_section = "calimero_abi_v1")]
16        static ABI: [u8; ABI_JSON.len()] = *ABI_JSON.as_bytes();
17
18        // Export functions to access the ABI at runtime
19        #[no_mangle]
20        pub extern "C" fn get_abi_ptr() -> u32 {
21            ABI.as_ptr() as u32
22        }
23
24        #[no_mangle]
25        pub extern "C" fn get_abi_len() -> u32 {
26            ABI.len() as u32
27        }
28
29        #[no_mangle]
30        pub extern "C" fn get_abi() -> u32 {
31            get_abi_ptr()
32        }
33    };
34}
35
36/// Embed ABI manifest into WASM binary
37#[must_use]
38pub fn embed(manifest: &Manifest) -> proc_macro2::TokenStream {
39    let json = serde_json::to_string(manifest).expect("Failed to serialize manifest");
40    let bytes = json.as_bytes();
41    let bytes_list = bytes
42        .iter()
43        .map(ToString::to_string)
44        .collect::<Vec<_>>()
45        .join(", ");
46    let json_len = bytes.len();
47
48    format!(
49        "// Generated ABI embed code\n// Create the custom section with the ABI JSON\n#[cfg_attr(target_os = \"macos\", link_section = \"__DATA,calimero_abi_v1\")]\n#[cfg_attr(not(target_os = \"macos\"), link_section = \"calimero_abi_v1\")]\nstatic ABI: [u8; {json_len}] = [{bytes_list}];\n\n// Export functions to access the ABI at runtime\n#[no_mangle]\npub extern \"C\" fn get_abi_ptr() -> u32 {{\n    ABI.as_ptr() as u32\n}}\n\n#[no_mangle]\npub extern \"C\" fn get_abi_len() -> u32 {{\n    ABI.len() as u32\n}}\n\n#[no_mangle]\npub extern \"C\" fn get_abi() -> u32 {{\n    get_abi_ptr()\n}}\n"
50    )
51    .parse()
52    .expect("Failed to parse generated code")
53}
54
55/// Generate embed code for build script
56#[must_use]
57pub fn generate_embed_code(manifest: &Manifest) -> String {
58    let json = serde_json::to_string(manifest).expect("Failed to serialize manifest");
59    let bytes = json.as_bytes();
60    let bytes_list = bytes
61        .iter()
62        .map(ToString::to_string)
63        .collect::<Vec<_>>()
64        .join(", ");
65    let json_len = bytes.len();
66
67    format!(
68        "// Generated ABI embed code\n// Create the custom section with the ABI JSON\n#[cfg_attr(target_os = \"macos\", link_section = \"__DATA,calimero_abi_v1\")]\n#[cfg_attr(not(target_os = \"macos\"), link_section = \"calimero_abi_v1\")]\nstatic ABI: [u8; {json_len}] = [{bytes_list}];\n\n// Export functions to access the ABI at runtime\n#[no_mangle]\npub extern \"C\" fn get_abi_ptr() -> u32 {{\n    ABI.as_ptr() as u32\n}}\n\n#[no_mangle]\npub extern \"C\" fn get_abi_len() -> u32 {{\n    ABI.len() as u32\n}}\n\n#[no_mangle]\npub extern \"C\" fn get_abi() -> u32 {{\n    get_abi_ptr()\n}}\n"
69    )
70}