nyar_runtime/vm/
mod.rs

1use wasmtime::{
2    component::{Component, Instance, Linker, ResourceTable},
3    Config, Engine, Store,
4};
5use wasmtime_wasi::preview2::{WasiCtx, WasiCtxBuilder, WasiView};
6
7use crate::{Debugger, host::NyarExtension};
8
9pub struct NyarVM {
10    store: Store<ContextView>,
11    instance: Instance,
12}
13
14impl NyarVM {
15    pub async fn load_wast(wast: &str) -> anyhow::Result<Self> {
16        let engine = get_engine()?;
17
18        let component = Component::new(&engine, wast.as_bytes())?;
19
20        let mut linker = Linker::<ContextView>::new(&engine);
21        linker.allow_shadowing(true);
22        wasmtime_wasi::preview2::command::add_to_linker(&mut linker)?;
23
24        Debugger::add_to_linker(&mut linker, |state| &mut state.extension)?;
25
26        let mut builder = WasiCtxBuilder::new();
27        builder.inherit_stderr();
28
29        let mut store = Store::new(&engine, ContextView::new(ResourceTable::default(), builder.build()));
30        let instance = linker.instantiate_async(&mut store, &component).await?;
31        Ok(Self { store, instance })
32    }
33}
34
35fn get_engine() -> anyhow::Result<Engine> {
36    let mut config = Config::new();
37    config.async_support(true);
38    config.wasm_reference_types(true);
39    config.wasm_function_references(true);
40    config.wasm_component_model(true);
41    Engine::new(&config)
42}
43
44pub struct ContextView {
45    wasi: WasiCtx,
46    resources: ResourceTable,
47    extension: NyarExtension,
48}
49
50impl ContextView {
51    fn new(table: ResourceTable, wasi: WasiCtx) -> Self {
52        Self { resources: table, wasi, extension: NyarExtension {} }
53    }
54}
55
56impl WasiView for ContextView {
57    fn table(&mut self) -> &mut ResourceTable {
58        &mut self.resources
59    }
60
61    fn ctx(&mut self) -> &mut WasiCtx {
62        &mut self.wasi
63    }
64}