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