#![forbid(unsafe_code)]
use anyhow::Result;
use wasmtime::component::Linker;
use wasmtime_wasi::p2::add_to_linker_sync;
use wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView};
use wasmtime_wasi_http::WasiHttpCtx;
use wasmtime_wasi_http::p2::{WasiHttpCtxView, WasiHttpView, add_only_http_to_linker_sync};
use wasmtime_wasi_tls::{
LinkOptions as WasiTlsLinkOptions, WasiTls, WasiTlsCtx, WasiTlsCtxBuilder,
};
pub struct DescribeHostState {
table: ResourceTable,
wasi: WasiCtx,
wasi_http: WasiHttpCtx,
wasi_tls: WasiTlsCtx,
}
impl Default for DescribeHostState {
fn default() -> Self {
let mut wasi = WasiCtxBuilder::new();
Self {
table: ResourceTable::new(),
wasi: wasi.build(),
wasi_http: WasiHttpCtx::new(),
wasi_tls: WasiTlsCtxBuilder::new().build(),
}
}
}
impl WasiView for DescribeHostState {
fn ctx(&mut self) -> WasiCtxView<'_> {
WasiCtxView {
table: &mut self.table,
ctx: &mut self.wasi,
}
}
}
impl WasiHttpView for DescribeHostState {
fn http(&mut self) -> WasiHttpCtxView<'_> {
WasiHttpCtxView {
ctx: &mut self.wasi_http,
table: &mut self.table,
hooks: Default::default(),
}
}
}
pub fn add_describe_host_imports(linker: &mut Linker<DescribeHostState>) -> Result<()> {
linker.allow_shadowing(true);
add_to_linker_sync(linker)
.map_err(|err| anyhow::anyhow!("register wasi preview2 describe host stubs: {err}"))?;
let mut tls_options = WasiTlsLinkOptions::default();
tls_options.tls(true);
wasmtime_wasi_tls::add_to_linker(linker, &mut tls_options, |host: &mut DescribeHostState| {
WasiTls::new(&host.wasi_tls, &mut host.table)
})
.map_err(|err| anyhow::anyhow!("register wasi tls describe host stubs: {err}"))?;
add_only_http_to_linker_sync(linker)
.map_err(|err| anyhow::anyhow!("register wasi http describe host stubs: {err}"))?;
Ok(())
}
pub fn stub_remaining_imports(
linker: &mut Linker<DescribeHostState>,
component: &wasmtime::component::Component,
) -> Result<()> {
linker
.define_unknown_imports_as_traps(component)
.map_err(|err| anyhow::anyhow!("stub remaining component imports: {err}"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_host_state_exposes_wasi_and_http_views() {
let mut state = DescribeHostState::default();
let ctx_view = state.ctx();
let _ = ctx_view.table;
let _ = ctx_view.ctx;
let http_view = state.http();
let _ = http_view.table;
let _ = http_view.ctx;
}
#[test]
fn describe_host_imports_register_without_error() {
let engine = wasmtime::Engine::default();
let mut linker = Linker::new(&engine);
add_describe_host_imports(&mut linker).expect("host imports should register");
}
}