Skip to main content

uni_plugin_wasm/
host_state.rs

1//! Per-`Store` host state.
2//!
3//! Every wasmtime `Store<T>` carries a `T` that the host's `Linker`
4//! references when wiring up imports. Our `T` is `HostState` — it
5//! holds:
6//!
7//! - **WASI context** — most Rust→wasm32-wasip2 plugins import
8//!   `wasi:cli`, `wasi:io`, `wasi:clocks`, etc., even when their
9//!   user-facing logic doesn't need filesystem / network access
10//!   (the standard library pulls these in transitively). Without
11//!   `wasmtime-wasi` linked, instantiation fails with
12//!   `component imports instance "wasi:io/poll@0.2.6", but a
13//!   matching implementation was not found in the linker`.
14//! - **Effective capability set** — so capability-gated host fns
15//!   can dispatch on the granted set.
16
17use std::sync::Arc;
18
19use uni_plugin::{CapabilitySet, HttpEgress};
20use wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView};
21
22/// State threaded through every wasmtime `Store<HostState>`.
23pub struct HostState {
24    /// Effective capability set (rich, with attenuation patterns) granted to
25    /// the plugin instance — capability-gated host fns dispatch + enforce
26    /// call-time attenuation against it.
27    pub effective: CapabilitySet,
28    /// HTTP egress backing the `host-net` interface, when granted + configured.
29    pub http: Option<Arc<dyn HttpEgress>>,
30    /// WASI context — minimal, no preopens, no inherited stdio.
31    /// Plugins requesting filesystem / network access go through
32    /// capability-gated host fns, not raw WASI preopens.
33    pub wasi: WasiCtx,
34    /// WASI resource table.
35    pub table: ResourceTable,
36}
37
38impl HostState {
39    /// Construct a fresh `HostState` with the given effective caps + egress.
40    ///
41    /// The WASI context starts minimal — no preopens, no inherited
42    /// stdio, no environment.
43    #[must_use]
44    pub fn new(effective: CapabilitySet, http: Option<Arc<dyn HttpEgress>>) -> Self {
45        let wasi = WasiCtxBuilder::new().build();
46        Self {
47            effective,
48            http,
49            wasi,
50            table: ResourceTable::new(),
51        }
52    }
53}
54
55impl std::fmt::Debug for HostState {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        f.debug_struct("HostState")
58            .field("effective", &self.effective)
59            .field("http", &self.http.is_some())
60            .finish_non_exhaustive()
61    }
62}
63
64impl WasiView for HostState {
65    fn ctx(&mut self) -> WasiCtxView<'_> {
66        WasiCtxView {
67            ctx: &mut self.wasi,
68            table: &mut self.table,
69        }
70    }
71}