use wasmtime::component::{Component, Linker, ResourceTable};
use wasmtime::*;
use wasmtime_wasi::p2::bindings::sync::Command;
use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
pub struct ComponentRunStates {
pub wasi_ctx: WasiCtx,
pub resource_table: ResourceTable,
}
impl WasiView for ComponentRunStates {
fn ctx(&mut self) -> WasiCtxView<'_> {
WasiCtxView {
ctx: &mut self.wasi_ctx,
table: &mut self.resource_table,
}
}
}
fn main() -> Result<()> {
let engine = Engine::default();
let mut linker = Linker::new(&engine);
wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
let wasi = WasiCtx::builder().inherit_stdio().inherit_args().build();
let state = ComponentRunStates {
wasi_ctx: wasi,
resource_table: ResourceTable::new(),
};
let mut store = Store::new(&engine, state);
let component = Component::from_file(&engine, "target/wasm32-wasip2/debug/wasi.wasm")?;
let command = Command::instantiate(&mut store, &component, &linker)?;
let program_result = command.wasi_cli_run().call_run(&mut store)?;
if program_result.is_err() {
std::process::exit(1)
}
let wasi = WasiCtx::builder().inherit_stdio().inherit_args().build();
let state = ComponentRunStates {
wasi_ctx: wasi,
resource_table: ResourceTable::new(),
};
let mut store = Store::new(&engine, state);
let instance = linker.instantiate(&mut store, &component)?;
let interface_idx = instance
.get_export_index(&mut store, None, "wasi:cli/run@0.2.0")
.expect("Cannot get `wasi:cli/run@0.2.0` interface");
let parent_export_idx = Some(&interface_idx);
let func_idx = instance
.get_export_index(&mut store, parent_export_idx, "run")
.expect("Cannot get `run` function in `wasi:cli/run@0.2.0` interface");
let func = instance
.get_func(&mut store, func_idx)
.expect("Unreachable since we've got func_idx");
let typed = func.typed::<(), (Result<(), ()>,)>(&store)?;
let (result,) = typed.call(&mut store, ())?;
result.map_err(|_| wasmtime::format_err!("error"))
}