Skip to main content

wasmtime_wasi/
view.rs

1use crate::WasiCtx;
2use wasmtime::component::ResourceTable;
3
4/// A trait which provides access to the [`WasiCtx`] inside the embedder's `T`
5/// of [`Store<T>`][`Store`].
6///
7/// This crate's WASI Host implementations depend on the contents of
8/// [`WasiCtx`]. The `T` type [`Store<T>`][`Store`] is defined in each
9/// embedding of Wasmtime. These implementations are connected to the
10/// [`Linker<T>`][`Linker`] by [`add_to_linker_async`](crate::p2::add_to_linker_async)
11/// functions.
12///
13/// # Example
14///
15/// ```
16/// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
17/// use wasmtime::component::ResourceTable;
18///
19/// struct MyState {
20///     ctx: WasiCtx,
21///     table: ResourceTable,
22/// }
23///
24/// impl WasiView for MyState {
25///     fn ctx(&mut self) -> WasiCtxView<'_> {
26///         WasiCtxView{
27///             ctx: &mut self.ctx,
28///             table: &mut self.table,
29///         }
30///     }
31/// }
32/// ```
33/// [`Store`]: wasmtime::Store
34/// [`Linker`]: wasmtime::component::Linker
35///
36pub trait WasiView: Send {
37    /// Yields mutable access to the [`WasiCtx`] configuration used for this
38    /// context.
39    fn ctx(&mut self) -> WasiCtxView<'_>;
40}
41
42/// Structure returned from [`WasiView::ctx`] which provides access to WASI
43/// state for host functions to be implemented with.
44pub struct WasiCtxView<'a> {
45    /// The [`WasiCtx`], or configuration, of the guest.
46    pub ctx: &'a mut WasiCtx,
47    /// Resources, such as files/streams, that the guest is using.
48    pub table: &'a mut ResourceTable,
49}
50
51impl<T: WasiView> crate::cli::WasiCliView for T {
52    fn cli(&mut self) -> crate::cli::WasiCliCtxView<'_> {
53        let WasiCtxView { ctx, table } = self.ctx();
54        crate::cli::WasiCliCtxView {
55            ctx: &mut ctx.cli,
56            table,
57        }
58    }
59}
60
61impl<T: WasiView> crate::clocks::WasiClocksView for T {
62    fn clocks(&mut self) -> crate::clocks::WasiClocksCtxView<'_> {
63        let WasiCtxView { ctx, table } = self.ctx();
64        crate::clocks::WasiClocksCtxView {
65            ctx: &mut ctx.clocks,
66            table,
67        }
68    }
69}
70
71impl<T: WasiView> crate::filesystem::WasiFilesystemView for T {
72    fn filesystem(&mut self) -> crate::filesystem::WasiFilesystemCtxView<'_> {
73        let WasiCtxView { ctx, table } = self.ctx();
74        crate::filesystem::WasiFilesystemCtxView {
75            ctx: &mut ctx.filesystem,
76            table,
77        }
78    }
79}
80
81impl<T: WasiView> crate::random::WasiRandomView for T {
82    fn random(&mut self) -> &mut crate::random::WasiRandomCtx {
83        &mut self.ctx().ctx.random
84    }
85}
86
87impl<T: WasiView> crate::sockets::WasiSocketsView for T {
88    fn sockets(&mut self) -> crate::sockets::WasiSocketsCtxView<'_> {
89        let WasiCtxView { ctx, table } = self.ctx();
90        crate::sockets::WasiSocketsCtxView {
91            ctx: &mut ctx.sockets,
92            table,
93        }
94    }
95}
96
97/// Identifier used to correlate a named import to a host-defined value.
98///
99/// This type is a small newtype wrapper around a `usize`, its only field which
100/// is also public. Embedders define the meaning of this value and are in control
101/// of both creating this and interpreting it. Creation of [`NamedId`] happens in
102/// functions like [`wasmtime_wasi::p3::add_named_to_linker`] where embedders
103/// will allocate a [`NamedId`] for all recognized named imports. Interpreting
104/// a [`NamedId`] happens later in traits such as [`WasiNamedView`] where the id
105/// is passed back to the embedder and a corresponding context must be returned.
106///
107/// Internally the `wasmtime-wasi` crate does not inspect the internal field
108/// here nor ever create one. Embedders are solely responsible for managing this
109/// id and its contents.
110///
111/// [`wasmtime_wasi::p3::add_named_to_linker`]: crate::p3::add_named_to_linker
112#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Debug)]
113pub struct NamedId(pub usize);
114
115/// A helper structure by which to implement generated-`Host` traits for
116/// bindings corresponding to named imports.
117///
118/// This is an implementation detail of how named imports are organized.
119/// Embedders invoking generated `add_to_linker` functions directly will be
120/// required to create this structure directly. Otherwise you probably won't
121/// need to interact with this.
122pub struct WasiCtxNamedView<'a, T>(pub &'a mut T);
123
124/// A trait which provides access to a specific [`WasiCtx`] as scoped by a
125/// [`NamedId`] parameter.
126///
127/// This trait is used as part of convenience
128/// [`wasmtime_wasi::p3::add_named_to_linker`] functions for example. This is
129/// used to scope access of a WASI context within a specific `id` or named
130/// import.
131///
132/// [`wasmtime_wasi::p3::add_named_to_linker`]: crate::p3::add_named_to_linker
133pub trait WasiNamedView: Send + 'static {
134    /// Yields mutable access to the [`WasiCtx`] configuration used for this
135    /// context.
136    ///
137    /// It's strongly recommended, though not always required, that the
138    /// [`ResourceTable`] in the returned [`WasiCtxView`] is the same table that
139    /// [`WasiView::ctx`] returns. Resources created through a named import can
140    /// be used through interfaces bound to the default context (and vice
141    /// versa), for example streams returned by a named `wasi:cli/stdout` are
142    /// used through `wasi:io/streams`, and with separate tables those lookups
143    /// fail or find another context's resources.
144    fn ctx(&mut self, id: NamedId) -> WasiCtxView<'_>;
145}
146
147impl<T: WasiNamedView> crate::cli::WasiCliNamedView for T {
148    fn cli(&mut self, id: NamedId) -> crate::cli::WasiCliCtxView<'_> {
149        let WasiCtxView { ctx, table } = self.ctx(id);
150        crate::cli::WasiCliCtxView {
151            ctx: &mut ctx.cli,
152            table,
153        }
154    }
155}
156
157impl<T: WasiNamedView> crate::clocks::WasiClocksNamedView for T {
158    fn clocks(&mut self, id: NamedId) -> crate::clocks::WasiClocksCtxView<'_> {
159        let WasiCtxView { ctx, table } = self.ctx(id);
160        crate::clocks::WasiClocksCtxView {
161            ctx: &mut ctx.clocks,
162            table,
163        }
164    }
165}
166
167impl<T: WasiNamedView> crate::filesystem::WasiFilesystemNamedView for T {
168    fn filesystem(&mut self, id: NamedId) -> crate::filesystem::WasiFilesystemCtxView<'_> {
169        let WasiCtxView { ctx, table } = self.ctx(id);
170        crate::filesystem::WasiFilesystemCtxView {
171            ctx: &mut ctx.filesystem,
172            table,
173        }
174    }
175}
176
177impl<T: WasiNamedView> crate::random::WasiRandomNamedView for T {
178    fn random(&mut self, id: NamedId) -> &mut crate::random::WasiRandomCtx {
179        self.ctx(id).ctx.random()
180    }
181}
182
183impl<T: WasiNamedView> crate::sockets::WasiSocketsNamedView for T {
184    fn sockets(&mut self, id: NamedId) -> crate::sockets::WasiSocketsCtxView<'_> {
185        let WasiCtxView { ctx, table } = self.ctx(id);
186        crate::sockets::WasiSocketsCtxView {
187            ctx: &mut ctx.sockets,
188            table,
189        }
190    }
191}