1 use anyhow::Result;
2 use wasmtime::{Engine, Instance, Linker, Module, Store};
3 
4 mod allocator;
5 
6 #[no_mangle]
7 pub unsafe extern "C" fn run(buf: *mut u8, size: usize) -> usize {
8     let buf = std::slice::from_raw_parts_mut(buf, size);
9     match run_result() {
10         Ok(()) => 0,
11         Err(e) => {
12             let msg = format!("{e:?}");
13             let len = buf.len().min(msg.len());
14             buf[..len].copy_from_slice(&msg.as_bytes()[..len]);
15             len
16         }
17     }
18 }
19 
20 fn run_result() -> Result<()> {
21     smoke()?;
22     simple_add()?;
23     simple_host_fn()?;
24     Ok(())
25 }
26 
27 fn smoke() -> Result<()> {
28     let engine = Engine::default();
29     let module = Module::new(&engine, "(module)")?;
30     Instance::new(&mut Store::new(&engine, ()), &module, &[])?;
31     Ok(())
32 }
33 
34 fn simple_add() -> Result<()> {
35     let engine = Engine::default();
36     let module = Module::new(
37         &engine,
38         r#"
39             (module
40                 (func (export "add") (param i32 i32) (result i32)
41                     (i32.add (local.get 0) (local.get 1)))
42             )
43         "#,
44     )?;
45     let mut store = Store::new(&engine, ());
46     let instance = Instance::new(&mut store, &module, &[])?;
47     let func = instance.get_typed_func::<(u32, u32), u32>(&mut store, "add")?;
48     assert_eq!(func.call(&mut store, (2, 3))?, 5);
49     Ok(())
50 }
51 
52 fn simple_host_fn() -> Result<()> {
53     let engine = Engine::default();
54     let module = Module::new(
55         &engine,
56         r#"
57             (module
58                 (import "host" "multiply" (func $multiply (param i32 i32) (result i32)))
59                 (func (export "add_and_mul") (param i32 i32 i32) (result i32)
60                     (i32.add (call $multiply (local.get 0) (local.get 1)) (local.get 2)))
61             )
62         "#,
63     )?;
64     let mut linker = Linker::<()>::new(&engine);
65     linker.func_wrap("host", "multiply", |a: u32, b: u32| a.saturating_mul(b))?;
66     let mut store = Store::new(&engine, ());
67     let instance = linker.instantiate(&mut store, &module)?;
68     let func = instance.get_typed_func::<(u32, u32, u32), u32>(&mut store, "add_and_mul")?;
69     assert_eq!(func.call(&mut store, (2, 3, 4))?, 10);
70     Ok(())
71 }
72