feat: add examples gcd, memory

This commit is contained in:
2023-01-19 00:01:28 +08:00
parent 3eefa3cba1
commit e6b985a695
2 changed files with 127 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
use anyhow::Result;
use wasmtime::*;
// https://docs.wasmtime.dev/examples-rust-gcd.html
fn main() -> Result<()> {
// Load our WebAssembly (parsed WAT in our case), and then load it into a
// `Module` which is attached to a `Store` cache. After we've got that we
// can instantiate it.
let mut store = Store::<()>::default();
let module = Module::new(store.engine(), r#"
(module
(func $gcd (param i32 i32) (result i32)
(local i32)
block ;; label = @1
block ;; label = @2
local.get 0
br_if 0 (;@2;)
local.get 1
local.set 2
br 1 (;@1;)
end
loop ;; label = @2
local.get 1
local.get 0
local.tee 2
i32.rem_u
local.set 0
local.get 2
local.set 1
local.get 0
br_if 0 (;@2;)
end
end
local.get 2
)
(export "gcd" (func $gcd))
)
"#)?;
let instance = Instance::new(&mut store, &module, &[])?;
// Invoke `gcd` export
let gcd = instance.get_typed_func::<(i32, i32), i32>(&mut store, "gcd")?;
println!("gcd(6, 27) = {}", gcd.call(&mut store, (6, 27))?);
Ok(())
}

View File

@@ -0,0 +1,81 @@
use anyhow::Result;
use wasmtime::*;
// https://docs.wasmtime.dev/examples-rust-memory.html
fn main() -> Result<()> {
// Create our `store_fn` context and then compile a module and create an
// instance from the compiled module all in one go.
let mut store: Store<()> = Store::default();
let module = Module::new(store.engine(), r#"
(module
(memory (export "memory") 2 3)
(func (export "size") (result i32) (memory.size))
(func (export "load") (param i32) (result i32)
(i32.load8_s (local.get 0))
)
(func (export "store") (param i32 i32)
(i32.store8 (local.get 0) (local.get 1))
)
(data (i32.const 0x1000) "\01\02\03\04")
)
"#)?;
let instance = Instance::new(&mut store, &module, &[])?;
// load_fn up our exports from the instance
let memory = instance
.get_memory(&mut store, "memory")
.ok_or(anyhow::format_err!("failed to find `memory` export"))?;
let size = instance.get_typed_func::<(), i32>(&mut store, "size")?;
let load_fn = instance.get_typed_func::<i32, i32>(&mut store, "load")?;
let store_fn = instance.get_typed_func::<(i32, i32), ()>(&mut store, "store")?;
println!("Checking memory...");
assert_eq!(memory.size(&store), 2);
assert_eq!(memory.data_size(&store), 0x20000);
assert_eq!(memory.data_mut(&mut store)[0], 0);
assert_eq!(memory.data_mut(&mut store)[0x1000], 1);
assert_eq!(memory.data_mut(&mut store)[0x1003], 4);
assert_eq!(size.call(&mut store, ())?, 2);
assert_eq!(load_fn.call(&mut store, 0)?, 0);
assert_eq!(load_fn.call(&mut store, 0x1000)?, 1);
assert_eq!(load_fn.call(&mut store, 0x1003)?, 4);
assert_eq!(load_fn.call(&mut store, 0x1ffff)?, 0);
assert!(load_fn.call(&mut store, 0x20000).is_err()); // out of bounds trap
println!("Mutating memory...");
memory.data_mut(&mut store)[0x1003] = 5;
store_fn.call(&mut store, (0x1002, 6))?;
assert!(store_fn.call(&mut store, (0x20000, 0)).is_err()); // out of bounds trap
assert_eq!(memory.data(&store)[0x1002], 6);
assert_eq!(memory.data(&store)[0x1003], 5);
assert_eq!(load_fn.call(&mut store, 0x1002)?, 6);
assert_eq!(load_fn.call(&mut store, 0x1003)?, 5);
// Grow memory.
println!("Growing memory...");
memory.grow(&mut store, 1)?;
assert_eq!(memory.size(&store), 3);
assert_eq!(memory.data_size(&store), 0x30000);
assert_eq!(load_fn.call(&mut store, 0x20000)?, 0);
store_fn.call(&mut store, (0x20000, 0))?;
assert!(load_fn.call(&mut store, 0x30000).is_err());
assert!(store_fn.call(&mut store, (0x30000, 0)).is_err());
assert!(memory.grow(&mut store, 1).is_err());
assert!(memory.grow(&mut store, 0).is_ok());
println!("Creating stand-alone memory...");
let memory_type = MemoryType::new(5, Some(5));
let memory2 = Memory::new(&mut store, memory_type)?;
assert_eq!(memory2.size(&store), 5);
assert!(memory2.grow(&mut store, 1).is_err());
assert!(memory2.grow(&mut store, 0).is_ok());
Ok(())
}