multiversx_sc_meta_lib/ei/
vm_hook_signature.rs

1use std::collections::HashMap;
2
3use wasmparser::ValType;
4
5use super::VM_HOOK_SIGNATURES;
6
7#[derive(Debug, Clone)]
8pub struct VmHookSignature {
9    pub name: &'static str,
10    pub params: &'static [ValType],
11    pub returns: Option<ValType>,
12}
13
14impl VmHookSignature {
15    pub const fn new(
16        name: &'static str,
17        params: &'static [ValType],
18        returns: Option<ValType>,
19    ) -> Self {
20        Self {
21            name,
22            params,
23            returns,
24        }
25    }
26
27    pub fn to_wat_func_type_declaration(&self, comment: &str) -> String {
28        let mut sc_wat = String::new();
29        sc_wat.push_str("(type");
30        sc_wat.push_str(comment);
31        sc_wat.push_str(" (func");
32        if !self.params.is_empty() {
33            sc_wat.push_str(" (param");
34            for param in self.params {
35                sc_wat.push(' ');
36                sc_wat.push_str(val_type_to_wat(*param));
37            }
38            sc_wat.push(')');
39        }
40        if let Some(ret) = self.returns {
41            sc_wat.push_str(" (result ");
42            sc_wat.push_str(val_type_to_wat(ret));
43            sc_wat.push(')');
44        }
45        sc_wat.push_str("))");
46        sc_wat
47    }
48}
49
50fn val_type_to_wat(val_type: ValType) -> &'static str {
51    match val_type {
52        ValType::I32 => "i32",
53        ValType::I64 => "i64",
54        _ => panic!("unsupported return type in vm hook signature"),
55    }
56}
57
58pub fn vm_hook_signature_map() -> HashMap<&'static str, VmHookSignature> {
59    let mut map = HashMap::new();
60    for vm_hook in VM_HOOK_SIGNATURES {
61        map.insert(vm_hook.name, vm_hook.clone());
62    }
63    map
64}
65
66pub fn check_vm_hook_signatures(
67    func_name: &str,
68    params: &[ValType],
69    returns: &[ValType],
70    signature_map: &HashMap<&'static str, VmHookSignature>,
71) {
72    let signature = signature_map
73        .get(func_name)
74        .unwrap_or_else(|| panic!("unknown vm hook function: {func_name}"));
75
76    assert_eq!(
77        signature.params, params,
78        "vm hook function {func_name} has invalid parameters"
79    );
80    match signature.returns {
81        Some(ret) => {
82            assert_eq!(
83                returns.len(),
84                1,
85                "vm hook function {func_name} must have exactly one return value"
86            );
87            assert_eq!(
88                returns[0], ret,
89                "vm hook function {func_name} has invalid return type"
90            );
91        }
92        None => {
93            assert!(
94                returns.is_empty(),
95                "vm hook function {func_name} must not have return values"
96            );
97        }
98    }
99}