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}