Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wiggle/tests/wasmtime_async.rs
3090 views
1
use wasmtime::{Engine, Linker, Module, Store, Val};
2
use wiggle::GuestMemory;
3
4
wiggle::from_witx!({
5
witx: ["tests/atoms.witx"],
6
async: {
7
atoms::{double_int_return_float}
8
}
9
});
10
11
pub struct Ctx;
12
impl wiggle::GuestErrorType for types::Errno {
13
fn success() -> Self {
14
types::Errno::Ok
15
}
16
}
17
18
impl atoms::Atoms for Ctx {
19
fn int_float_args(
20
&mut self,
21
_: &mut GuestMemory<'_>,
22
an_int: u32,
23
an_float: f32,
24
) -> Result<(), types::Errno> {
25
println!("INT FLOAT ARGS: {an_int} {an_float}");
26
Ok(())
27
}
28
async fn double_int_return_float(
29
&mut self,
30
_: &mut GuestMemory<'_>,
31
an_int: u32,
32
) -> Result<types::AliasToFloat, types::Errno> {
33
// Do something inside this test that is Pending for a trivial amount of time,
34
// to make sure we are hooked up to the tokio executor properly.
35
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
36
Ok((an_int as f32) * 2.0)
37
}
38
}
39
40
#[tokio::test]
41
async fn test_sync_host_func() {
42
let mut store = async_store();
43
let mut linker = Linker::<Ctx>::new(store.engine());
44
atoms::add_to_linker(&mut linker, |cx| cx).unwrap();
45
let shim_mod = shim_module(linker.engine());
46
let shim_inst = linker
47
.instantiate_async(&mut store, &shim_mod)
48
.await
49
.unwrap();
50
51
let mut results = [Val::I32(0)];
52
shim_inst
53
.get_func(&mut store, "int_float_args_shim")
54
.unwrap()
55
.call_async(&mut store, &[0i32.into(), 123.45f32.into()], &mut results)
56
.await
57
.unwrap();
58
59
assert_eq!(
60
results[0].unwrap_i32(),
61
types::Errno::Ok as i32,
62
"int_float_args errno"
63
);
64
}
65
66
#[tokio::test]
67
async fn test_async_host_func() {
68
let mut store = async_store();
69
let mut linker = Linker::<Ctx>::new(store.engine());
70
atoms::add_to_linker(&mut linker, |cx| cx).unwrap();
71
72
let shim_mod = shim_module(linker.engine());
73
let shim_inst = linker
74
.instantiate_async(&mut store, &shim_mod)
75
.await
76
.unwrap();
77
78
let input: i32 = 123;
79
let result_location: i32 = 0;
80
81
let mut results = [Val::I32(0)];
82
shim_inst
83
.get_func(&mut store, "double_int_return_float_shim")
84
.unwrap()
85
.call_async(
86
&mut store,
87
&[input.into(), result_location.into()],
88
&mut results,
89
)
90
.await
91
.unwrap();
92
93
assert_eq!(
94
results[0].unwrap_i32(),
95
types::Errno::Ok as i32,
96
"double_int_return_float errno"
97
);
98
99
// The actual result is in memory:
100
let mem = shim_inst.get_memory(&mut store, "memory").unwrap();
101
let mut result_bytes: [u8; 4] = [0, 0, 0, 0];
102
mem.read(&store, result_location as usize, &mut result_bytes)
103
.unwrap();
104
let result = f32::from_le_bytes(result_bytes);
105
assert_eq!((input * 2) as f32, result);
106
}
107
108
fn async_store() -> Store<Ctx> {
109
Store::new(&Engine::default(), Ctx)
110
}
111
112
// Wiggle expects the caller to have an exported memory. Wasmtime can only
113
// provide this if the caller is a WebAssembly module, so we need to write
114
// a shim module:
115
fn shim_module(engine: &Engine) -> Module {
116
Module::new(
117
engine,
118
r#"
119
(module
120
(import "atoms" "int_float_args" (func $int_float_args (param i32 f32) (result i32)))
121
(import "atoms" "double_int_return_float" (func $double_int_return_float (param i32 i32) (result i32)))
122
123
(memory 1)
124
(export "memory" (memory 0))
125
126
(func $int_float_args_shim (param i32 f32) (result i32)
127
local.get 0
128
local.get 1
129
call $int_float_args
130
)
131
(func $double_int_return_float_shim (param i32 i32) (result i32)
132
local.get 0
133
local.get 1
134
call $double_int_return_float
135
)
136
(export "int_float_args_shim" (func $int_float_args_shim))
137
(export "double_int_return_float_shim" (func $double_int_return_float_shim))
138
)
139
"#,
140
)
141
.unwrap()
142
}
143
144