wasm_embedded_rt_wasmtime/
lib.rs1pub use wasm_embedded_spec::{self as spec};
5
6use spec::Error;
7use spec::api::{UserErrorConversion, types::Errno};
8
9use wasmtime::*;
10use wasmtime_wasi::{WasiCtx, WasiCtxBuilder};
11
12
13mod gpio;
14mod spi;
15mod i2c;
16mod uart;
17
18pub struct WasmtimeRuntime<E> {
20 _engine: wasmtime::Engine,
21 linker: Linker<Context<E>>,
22 store: Store<Context<E>>,
23}
24
25struct Context<E> {
26 wasi: WasiCtx,
27 engine: E,
28}
29
30pub trait Engine: spec::gpio::Gpio + spec::i2c::I2c + spec::spi::Spi + spec::uart::Uart {}
31
32impl <T> Engine for T where
33 T: spec::gpio::Gpio + spec::i2c::I2c + spec::spi::Spi + spec::uart::Uart,
34{
35}
36
37impl <E: Engine> Context<E> {
38 pub fn new(engine: E) -> Self {
39
40 let wasi = WasiCtxBuilder::new()
41 .inherit_stdio()
42 .inherit_args().unwrap()
43 .build();
44
45 Context {
46 wasi,
47 engine
48 }
49 }
50}
51
52impl <E: Engine> UserErrorConversion for Context<E> {
53 fn errno_from_error(&mut self, e: spec::Error) -> Result<spec::api::types::Errno, anyhow::Error> {
54 match e {
55 Error::InvalidArg => Ok(Errno::InvalidArg),
56 Error::Unexpected => Ok(Errno::Unexpected),
57 Error::Failed => Ok(Errno::Failed),
58 Error::NoDevice => Ok(Errno::NoDevice),
59 Error::Unsupported => Ok(Errno::Unsupported),
60 }
61 }
62}
63
64impl <E: Engine + 'static> WasmtimeRuntime<E> {
65 pub fn new(engine: E, bin: &[u8]) -> anyhow::Result<Self> {
67 let wasm_engine = wasmtime::Engine::default();
69 let mut linker = Linker::new(&wasm_engine);
70
71 let context = Context::new(engine);
73 let mut store = Store::new(&wasm_engine, context);
74
75 wasmtime_wasi::add_to_linker(&mut linker, |ctx: &mut Context<E>| &mut ctx.wasi )?;
77
78 spec::api::gpio::add_to_linker(&mut linker, move |c: &mut Context<E>| c)?;
80 spec::api::spi::add_to_linker(&mut linker, move |c: &mut Context<E>| c)?;
81 spec::api::i2c::add_to_linker(&mut linker, move |c: &mut Context<E>| c)?;
82 spec::api::uart::add_to_linker(&mut linker, move |c: &mut Context<E>| c)?;
83
84 let module = Module::from_binary(&wasm_engine, bin)?;
86 linker.module(&mut store, "", &module)?;
87
88 Ok(Self{ _engine: wasm_engine, linker, store })
89 }
90
91 pub fn run(&mut self) -> anyhow::Result<()> {
93 let Self{linker, ..} = self;
94
95 linker
96 .get_default(&mut self.store, "")?
97 .typed::<(), (), _>(&self.store)?
98 .call(&mut self.store, ())?;
99
100 Ok(())
101 }
102}