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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use wasmtime::Instance;
use serde::{Serialize, Deserialize};
use wasi_binio_shared_mods::{split_i64_to_i32};
fn reserve_wasm_memory_buffer<'a, T> (value: &T, instance: &Instance ) -> Result<(i32, i32), &'a str> where T: Serialize {
let buffer_size = bincode::serialized_size(value).expect("Error when calculate the buffer size using bincode") as i32;
let prepare_buffer_func = instance
.get_export("prepare_buffer")
.and_then(|e| e.func())
.expect("Cannot get exported function 'prepare_buffer' from wasm instance")
.get1::<i32, i64>().expect("Cannot get exported function 'prepare_buffer' from wasm instance");
let result = prepare_buffer_func(buffer_size).expect("Error in prepare_buffer_func");
Ok(split_i64_to_i32(result))
}
fn fill_buffer<T> (value: &T, instance: &Instance, ptr:i32, len:i32) -> Result<(), &'static str> where T: Serialize {
let mem = instance.get_export("memory").expect("Cannot get export memory from instance").memory().expect("cannot get memory");
let mem_array: &mut [u8];
let serialized_array = bincode::serialize(value).expect("Error inside bincode::serialize");
unsafe{
mem_array = mem.data_unchecked_mut();
for i in 0..len {
mem_array[ptr as usize + i as usize] = serialized_array[i as usize];
}
}
Ok(())
}
pub fn call_stub <'a, T, R> (instance: &'a Instance, arg: &T, func_name: &str) -> R
where T: Serialize, R: Deserialize<'a> {
let (arg_buffer_ptr, arg_buffer_len) = reserve_wasm_memory_buffer(arg, instance).expect("Error inside reserve_wasm_memory_buffer");
fill_buffer(&arg, instance, arg_buffer_ptr, arg_buffer_len).expect("fill_buffer has error");
let wasm_func = instance
.get_export(func_name)
.and_then(|e| e.func())
.expect(&format!("call_stub cannot get exported function name: {} from wasm instance. Please make sure you exported such a function", func_name))
.get2::<i32, i32, i64>().expect(&format!("call_stub cannot get correct FuncType for function name: {} from wasm instance. Please make sure you exported such a function", func_name));
let result_in_i64 = wasm_func(arg_buffer_ptr, arg_buffer_len).expect("do_compute error");
let (result_buffer_ptr, result_buffer_len) = split_i64_to_i32(result_in_i64);
let mem = instance.get_export("memory").expect("Error exporting memory from instance").memory().expect("memory fail");
let mem_array_ref = unsafe {mem.data_unchecked()};
let start_ptr = mem_array_ref.as_ptr().wrapping_offset(result_buffer_ptr as isize);
let a = unsafe{std::slice::from_raw_parts(start_ptr, result_buffer_len as usize)};
bincode::deserialize(a).expect("deseralize error")
}