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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::malloc::alloc;

#[link(wasm_import_module = "wrap")]
extern "C" {
    /// Get Invoke Arguments
    #[link_name = "__wrap_invoke_args"]
    pub fn __wrap_invoke_args(method_ptr: u32, args_ptr: u32);

    /// Set Invoke Result
    #[link_name = "__wrap_invoke_result"]
    pub fn __wrap_invoke_result(ptr: u32, len: u32);

    /// Set Invoke Error
    #[link_name = "__wrap_invoke_error"]
    pub fn __wrap_invoke_error(ptr: u32, len: u32);
}

/// Keep track of all invokable functions
pub type InvokeFunction = fn(args_buf: &[u8], env_size: u32) -> Vec<u8>;

pub struct InvokeArgs {
    pub method: String,
    pub args: Vec<u8>,
}

/// Helper for fetching invoke args
pub fn wrap_invoke_args(method_size: u32, args_size: u32) -> InvokeArgs {
    let method_size_ptr = alloc(method_size as usize);
    let args_size_ptr = alloc(args_size as usize);

    unsafe { __wrap_invoke_args(method_size_ptr as u32, args_size_ptr as u32) };

    let method = unsafe {
        String::from_raw_parts(method_size_ptr, method_size as usize, method_size as usize)
    };
    let args =
        unsafe { Vec::from_raw_parts(args_size_ptr, args_size as usize, args_size as usize) };

    InvokeArgs { method, args }
}

/// Helper for handling `_wrap_invoke`
pub fn wrap_invoke(args: InvokeArgs, env_size: u32, opt_invoke_func: Option<InvokeFunction>) -> bool {
    match opt_invoke_func {
        Some(func) => {
            let result = func(args.args.as_slice(), env_size);
            let res_len = result.len() as u32;
            unsafe { __wrap_invoke_result(result.as_ptr() as u32, res_len) };
            true
        }
        None => {
            let message = format!("Could not find invoke function {}", &args.method);
            let msg_bytes = message.as_bytes();
            let msg_len = msg_bytes.len() as u32;
            unsafe { __wrap_invoke_error(msg_bytes.as_ptr() as u32, msg_len) };
            false
        }
    }
}

/// Helper for handling `wrap_invoke_result`
pub fn wrap_invoke_result(result: Vec<u8>) {
    let res_len = result.len() as u32;
    unsafe { __wrap_invoke_result(result.as_ptr() as u32, res_len) };
}

/// Helper for handling `wrap_invoke_error`
pub fn wrap_invoke_error(message: String) {
    let msg_bytes = message.as_bytes();
    let msg_len = msg_bytes.len() as u32;
    unsafe { __wrap_invoke_error(msg_bytes.as_ptr() as u32, msg_len) };
}