1 //! # Wasmtime's WASIp2 Implementation
2 //!
3 //!
4 //! This module provides a Wasmtime host implementation of WASI 0.2 (aka WASIp2
5 //! aka Preview 2) and WASI 0.1 (aka WASIp1 aka Preview 1). WASI is implemented
6 //! with the Rust crates [`tokio`] and [`cap-std`] primarily, meaning that
7 //! operations are implemented in terms of their native platform equivalents by
8 //! default.
9 //!
10 //! # WASIp2 interfaces
11 //!
12 //! This module contains implementations of the following interfaces:
13 //!
14 //! * [`wasi:cli/environment`]
15 //! * [`wasi:cli/exit`]
16 //! * [`wasi:cli/stderr`]
17 //! * [`wasi:cli/stdin`]
18 //! * [`wasi:cli/stdout`]
19 //! * [`wasi:cli/terminal-input`]
20 //! * [`wasi:cli/terminal-output`]
21 //! * [`wasi:cli/terminal-stderr`]
22 //! * [`wasi:cli/terminal-stdin`]
23 //! * [`wasi:cli/terminal-stdout`]
24 //! * [`wasi:clocks/monotonic-clock`]
25 //! * [`wasi:clocks/wall-clock`]
26 //! * [`wasi:filesystem/preopens`]
27 //! * [`wasi:filesystem/types`]
28 //! * [`wasi:random/insecure-seed`]
29 //! * [`wasi:random/insecure`]
30 //! * [`wasi:random/random`]
31 //! * [`wasi:sockets/instance-network`]
32 //! * [`wasi:sockets/ip-name-lookup`]
33 //! * [`wasi:sockets/network`]
34 //! * [`wasi:sockets/tcp-create-socket`]
35 //! * [`wasi:sockets/tcp`]
36 //! * [`wasi:sockets/udp-create-socket`]
37 //! * [`wasi:sockets/udp`]
38 //!
39 //! Most traits are implemented for [`WasiCtxView`] trait which provides
40 //! access to [`WasiCtx`] and [`ResourceTable`], which defines the configuration
41 //! for WASI and handle state. The [`WasiView`] trait is used to acquire and
42 //! construct a [`WasiCtxView`].
43 //!
44 //! The [`wasmtime-wasi-io`] crate contains implementations of the
45 //! following interfaces, and this module reuses those implementations:
46 //!
47 //! * [`wasi:io/error`]
48 //! * [`wasi:io/poll`]
49 //! * [`wasi:io/streams`]
50 //!
51 //! These traits are implemented directly for [`ResourceTable`]. All aspects of
52 //! `wasmtime-wasi-io` that are used by this module are re-exported. Unless you
53 //! are implementing other host functionality that needs to interact with the
54 //! WASI scheduler and don't want to use other functionality provided by
55 //! `wasmtime-wasi`, you don't need to take a direct dependency on
56 //! `wasmtime-wasi-io`.
57 //!
58 //! # Generated Bindings
59 //!
60 //! This module uses [`wasmtime::component::bindgen!`] to generate bindings for
61 //! all WASI interfaces. Raw bindings are available in the [`bindings`] submodule
62 //! of this module. Downstream users can either implement these traits themselves
63 //! or you can use the built-in implementations in this module for
64 //! `WasiImpl<T: WasiView>`.
65 //!
66 //! # The `WasiView` trait
67 //!
68 //! This module's implementation of WASI is done in terms of an implementation of
69 //! [`WasiView`]. This trait provides a "view" into WASI-related state that is
70 //! contained within a [`Store<T>`](wasmtime::Store).
71 //!
72 //! For all of the generated bindings in this module (Host traits),
73 //! implementations are provided looking like:
74 //!
75 //! ```
76 //! # use wasmtime_wasi::WasiCtxView;
77 //! # trait WasiView {}
78 //! # mod bindings { pub mod wasi { pub trait Host {} } }
79 //! impl bindings::wasi::Host for WasiCtxView<'_> {
80 //! // ...
81 //! }
82 //! ```
83 //!
84 //! where the [`WasiCtxView`] type comes from [`WasiView::ctx`] for the type
85 //! contained within the `Store<T>`. The [`add_to_linker_sync`] and
86 //! [`add_to_linker_async`] function then require that `T: WasiView` with
87 //! [`Linker<T>`](wasmtime::component::Linker).
88 //!
89 //! To implement the [`WasiView`] trait you will first select a
90 //! `T` to put in `Store<T>` (typically, by defining your own struct).
91 //! Somewhere within `T` you'll store:
92 //!
93 //! * [`ResourceTable`] - created through default constructors.
94 //! * [`WasiCtx`] - created through [`WasiCtxBuilder`].
95 //!
96 //! You'll then write an implementation of the [`WasiView`]
97 //! trait to access those items in your `T`. For example:
98 //! ```
99 //! use wasmtime::component::ResourceTable;
100 //! use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
101 //!
102 //! struct MyCtx {
103 //! table: ResourceTable,
104 //! wasi: WasiCtx,
105 //! }
106 //!
107 //! impl WasiView for MyCtx {
108 //! fn ctx(&mut self) -> WasiCtxView<'_> {
109 //! WasiCtxView { ctx: &mut self.wasi, table: &mut self.table }
110 //! }
111 //! }
112 //! ```
113 //!
114 //! # Async and Sync
115 //!
116 //! All WASIp2 functions are blocking from WebAssembly's point of view: a
117 //! WebAssembly call into these functions returns only when they are complete.
118 //!
119 //! This module provides an implementation of those functions in the host, where
120 //! for some functions, it is appropriate to implement them using async Rust and
121 //! the Tokio executor. The host implementation still blocks WebAssembly, but it
122 //! does not block the host's thread. Synchronous wrappers are also provided for
123 //! all async implementations, which create a private Tokio executor.
124 //!
125 //! Users can choose between these modes of implementation using variants
126 //! of the add_to_linker functions:
127 //!
128 //! * For non-async users, use [`add_to_linker_sync`].
129 //! * For async users, use [`add_to_linker_async`].
130 //!
131 //! Note that bindings are generated once for async and once for sync. Most
132 //! interfaces do not change, however, so only interfaces with blocking
133 //! functions have bindings generated twice. Bindings are organized as:
134 //!
135 //! * [`bindings`] - default location of all bindings, blocking functions are
136 //! `async`
137 //! * [`bindings::sync`] - blocking interfaces have synchronous versions here.
138 //!
139 //! # Module-specific traits
140 //!
141 //! This module's default implementation of WASI bindings to native primitives
142 //! for the platform that it is compiled for. For example opening a TCP socket
143 //! uses the native platform to open a TCP socket (so long as [`WasiCtxBuilder`]
144 //! allows it). There are a few important traits, however, that are specific to
145 //! this module.
146 //!
147 //! * [`InputStream`] and [`OutputStream`] - these are the host traits
148 //! behind the WASI `input-stream` and `output-stream` types in the
149 //! `wasi:io/streams` interface. These enable embedders to build their own
150 //! custom stream and insert them into a [`ResourceTable`] (as a boxed trait
151 //! object, see [`DynInputStream`] and [`DynOutputStream`]) to be used from
152 //! wasm.
153 //!
154 //! * [`Pollable`] - this trait enables building arbitrary logic to get hooked
155 //! into a `pollable` resource from `wasi:io/poll`. A pollable resource is
156 //! created through the [`subscribe`] function.
157 //!
158 //! * [`HostWallClock`](crate::HostWallClock) and [`HostMonotonicClock`](crate::HostMonotonicClock) are used in conjunction with
159 //! [`WasiCtxBuilder::wall_clock`] and [`WasiCtxBuilder::monotonic_clock`] if
160 //! the defaults host's clock should not be used.
161 //!
162 //! * [`StdinStream`] and [`StdoutStream`] are used to provide custom
163 //! stdin/stdout streams if they're not inherited (or null, which is the
164 //! default).
165 //!
166 //! These traits enable embedders to customize small portions of WASI interfaces
167 //! provided while still providing all other interfaces.
168 //!
169 //! # Examples
170 //!
171 //! Usage of this module is done through a few steps to get everything hooked up:
172 //!
173 //! 1. First implement [`WasiView`] for your type which is the
174 //! `T` in `Store<T>`.
175 //! 2. Add WASI interfaces to a `wasmtime::component::Linker<T>`. This is either
176 //! done through top-level functions like [`add_to_linker_sync`] or through
177 //! individual `add_to_linker` functions in generated bindings throughout
178 //! this module.
179 //! 3. Create a [`WasiCtx`] for each `Store<T>` through [`WasiCtxBuilder`]. Each
180 //! WASI context is "null" or "empty" by default, so items must be explicitly
181 //! added to get accessed by wasm (such as env vars or program arguments).
182 //! 4. Use the previous `Linker<T>` to instantiate a `Component` within a
183 //! `Store<T>`.
184 //!
185 //! For examples see each of [`WasiView`], [`WasiCtx`], [`WasiCtxBuilder`],
186 //! [`add_to_linker_sync`], and [`bindings::Command`].
187 //!
188 //! [`wasmtime::component::bindgen!`]: https://docs.rs/wasmtime/latest/wasmtime/component/macro.bindgen.html
189 //! [`tokio`]: https://crates.io/crates/tokio
190 //! [`cap-std`]: https://crates.io/crates/cap-std
191 //! [`wasmtime-wasi-io`]: https://crates.io/crates/wasmtime-wasi-io
192 //! [`wasi:cli/environment`]: bindings::cli::environment::Host
193 //! [`wasi:cli/exit`]: bindings::cli::exit::Host
194 //! [`wasi:cli/stderr`]: bindings::cli::stderr::Host
195 //! [`wasi:cli/stdin`]: bindings::cli::stdin::Host
196 //! [`wasi:cli/stdout`]: bindings::cli::stdout::Host
197 //! [`wasi:cli/terminal-input`]: bindings::cli::terminal_input::Host
198 //! [`wasi:cli/terminal-output`]: bindings::cli::terminal_output::Host
199 //! [`wasi:cli/terminal-stdin`]: bindings::cli::terminal_stdin::Host
200 //! [`wasi:cli/terminal-stdout`]: bindings::cli::terminal_stdout::Host
201 //! [`wasi:cli/terminal-stderr`]: bindings::cli::terminal_stderr::Host
202 //! [`wasi:clocks/monotonic-clock`]: bindings::clocks::monotonic_clock::Host
203 //! [`wasi:clocks/wall-clock`]: bindings::clocks::wall_clock::Host
204 //! [`wasi:filesystem/preopens`]: bindings::filesystem::preopens::Host
205 //! [`wasi:filesystem/types`]: bindings::filesystem::types::Host
206 //! [`wasi:io/error`]: wasmtime_wasi_io::bindings::wasi::io::error::Host
207 //! [`wasi:io/poll`]: wasmtime_wasi_io::bindings::wasi::io::poll::Host
208 //! [`wasi:io/streams`]: wasmtime_wasi_io::bindings::wasi::io::streams::Host
209 //! [`wasi:random/insecure-seed`]: bindings::random::insecure_seed::Host
210 //! [`wasi:random/insecure`]: bindings::random::insecure::Host
211 //! [`wasi:random/random`]: bindings::random::random::Host
212 //! [`wasi:sockets/instance-network`]: bindings::sockets::instance_network::Host
213 //! [`wasi:sockets/ip-name-lookup`]: bindings::sockets::ip_name_lookup::Host
214 //! [`wasi:sockets/network`]: bindings::sockets::network::Host
215 //! [`wasi:sockets/tcp-create-socket`]: bindings::sockets::tcp_create_socket::Host
216 //! [`wasi:sockets/tcp`]: bindings::sockets::tcp::Host
217 //! [`wasi:sockets/udp-create-socket`]: bindings::sockets::udp_create_socket::Host
218 //! [`wasi:sockets/udp`]: bindings::sockets::udp::Host
219 //! [`ResourceTable`]: wasmtime::component::ResourceTable
220 //! [`WasiCtx`]: crate::WasiCtx
221 //! [`WasiCtxView`]: crate::WasiCtxView
222 //! [`WasiCtxBuilder`]: crate::WasiCtxBuilder
223 //! [`WasiCtxBuilder::wall_clock`]: crate::WasiCtxBuilder::wall_clock
224 //! [`WasiCtxBuilder::monotonic_clock`]: crate::WasiCtxBuilder::monotonic_clock
225 //! [`StdinStream`]: crate::cli::StdinStream
226 //! [`StdoutStream`]: crate::cli::StdoutStream
227
228 use crate::WasiView;
229 use crate::cli::{WasiCli, WasiCliView as _};
230 use crate::clocks::{WasiClocks, WasiClocksView as _};
231 use crate::filesystem::{WasiFilesystem, WasiFilesystemView as _};
232 use crate::random::WasiRandom;
233 use crate::sockets::{WasiSockets, WasiSocketsView as _};
234 use wasmtime::component::{HasData, Linker, ResourceTable};
235
236 pub mod bindings;
237 pub(crate) mod filesystem;
238 mod host;
239 mod ip_name_lookup;
240 mod network;
241 pub mod pipe;
242 mod poll;
243 mod stdio;
244 mod tcp;
245 mod udp;
246 mod write_stream;
247
248 pub use self::filesystem::{FsError, FsResult, ReaddirIterator};
249 pub use self::network::{Network, SocketError, SocketResult};
250 pub use self::stdio::IsATTY;
251 pub(crate) use tcp::P2TcpStreamingState;
252 // These contents of wasmtime-wasi-io are re-exported by this module for compatibility:
253 // they were originally defined in this module before being factored out, and many
254 // users of this module depend on them at these names.
255 pub use wasmtime_wasi_io::poll::{DynFuture, DynPollable, MakeFuture, Pollable, subscribe};
256 pub use wasmtime_wasi_io::streams::{
257 DynInputStream, DynOutputStream, Error as IoError, InputStream, OutputStream, StreamError,
258 StreamResult,
259 };
260
261 /// Add all WASI interfaces from this crate into the `linker` provided.
262 ///
263 /// This function will add the `async` variant of all interfaces into the
264 /// [`Linker`] provided. For embeddings with async support disabled see
265 /// [`add_to_linker_sync`] instead.
266 ///
267 /// This function will add all interfaces implemented by this crate to the
268 /// [`Linker`], which corresponds to the `wasi:cli/imports` world supported by
269 /// this crate.
270 ///
271 /// # Example
272 ///
273 /// ```
274 /// use wasmtime::{Engine, Result, Store, Config};
275 /// use wasmtime::component::{ResourceTable, Linker};
276 /// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
277 ///
278 /// fn main() -> Result<()> {
279 /// let engine = Engine::default();
280 ///
281 /// let mut linker = Linker::<MyState>::new(&engine);
282 /// wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
283 /// // ... add any further functionality to `linker` if desired ...
284 ///
285 /// let mut builder = WasiCtx::builder();
286 ///
287 /// // ... configure `builder` more to add env vars, args, etc ...
288 ///
289 /// let mut store = Store::new(
290 /// &engine,
291 /// MyState {
292 /// ctx: builder.build(),
293 /// table: ResourceTable::new(),
294 /// },
295 /// );
296 ///
297 /// // ... use `linker` to instantiate within `store` ...
298 ///
299 /// Ok(())
300 /// }
301 ///
302 /// struct MyState {
303 /// ctx: WasiCtx,
304 /// table: ResourceTable,
305 /// }
306 ///
307 /// impl WasiView for MyState {
308 /// fn ctx(&mut self) -> WasiCtxView<'_> {
309 /// WasiCtxView { ctx: &mut self.ctx, table: &mut self.table }
310 /// }
311 /// }
312 /// ```
add_to_linker_async<T: WasiView>(linker: &mut Linker<T>) -> wasmtime::Result<()>313 pub fn add_to_linker_async<T: WasiView>(linker: &mut Linker<T>) -> wasmtime::Result<()> {
314 let options = bindings::LinkOptions::default();
315 add_to_linker_with_options_async(linker, &options)
316 }
317
318 /// Similar to [`add_to_linker_async`], but with the ability to enable unstable features.
add_to_linker_with_options_async<T: WasiView>( linker: &mut Linker<T>, options: &bindings::LinkOptions, ) -> wasmtime::Result<()>319 pub fn add_to_linker_with_options_async<T: WasiView>(
320 linker: &mut Linker<T>,
321 options: &bindings::LinkOptions,
322 ) -> wasmtime::Result<()> {
323 add_async_io_to_linker(linker)?;
324 add_nonblocking_to_linker(linker, options)?;
325
326 let l = linker;
327 bindings::filesystem::types::add_to_linker::<T, WasiFilesystem>(l, T::filesystem)?;
328 bindings::sockets::tcp::add_to_linker::<T, WasiSockets>(l, T::sockets)?;
329 bindings::sockets::udp::add_to_linker::<T, WasiSockets>(l, T::sockets)?;
330 Ok(())
331 }
332
333 /// Shared functionality for [`add_to_linker_async`] and [`add_to_linker_sync`].
add_nonblocking_to_linker<'a, T: WasiView, O>( linker: &mut Linker<T>, options: &'a O, ) -> wasmtime::Result<()> where bindings::sockets::network::LinkOptions: From<&'a O>, bindings::cli::exit::LinkOptions: From<&'a O>,334 fn add_nonblocking_to_linker<'a, T: WasiView, O>(
335 linker: &mut Linker<T>,
336 options: &'a O,
337 ) -> wasmtime::Result<()>
338 where
339 bindings::sockets::network::LinkOptions: From<&'a O>,
340 bindings::cli::exit::LinkOptions: From<&'a O>,
341 {
342 use crate::p2::bindings::{cli, clocks, filesystem, random, sockets};
343
344 let l = linker;
345 clocks::wall_clock::add_to_linker::<T, WasiClocks>(l, T::clocks)?;
346 clocks::monotonic_clock::add_to_linker::<T, WasiClocks>(l, T::clocks)?;
347 filesystem::preopens::add_to_linker::<T, WasiFilesystem>(l, T::filesystem)?;
348 random::random::add_to_linker::<T, WasiRandom>(l, |t| &mut t.ctx().ctx.random)?;
349 random::insecure::add_to_linker::<T, WasiRandom>(l, |t| &mut t.ctx().ctx.random)?;
350 random::insecure_seed::add_to_linker::<T, WasiRandom>(l, |t| &mut t.ctx().ctx.random)?;
351 cli::exit::add_to_linker::<T, WasiCli>(l, &options.into(), T::cli)?;
352 cli::environment::add_to_linker::<T, WasiCli>(l, T::cli)?;
353 cli::stdin::add_to_linker::<T, WasiCli>(l, T::cli)?;
354 cli::stdout::add_to_linker::<T, WasiCli>(l, T::cli)?;
355 cli::stderr::add_to_linker::<T, WasiCli>(l, T::cli)?;
356 cli::terminal_input::add_to_linker::<T, WasiCli>(l, T::cli)?;
357 cli::terminal_output::add_to_linker::<T, WasiCli>(l, T::cli)?;
358 cli::terminal_stdin::add_to_linker::<T, WasiCli>(l, T::cli)?;
359 cli::terminal_stdout::add_to_linker::<T, WasiCli>(l, T::cli)?;
360 cli::terminal_stderr::add_to_linker::<T, WasiCli>(l, T::cli)?;
361 sockets::tcp_create_socket::add_to_linker::<T, WasiSockets>(l, T::sockets)?;
362 sockets::udp_create_socket::add_to_linker::<T, WasiSockets>(l, T::sockets)?;
363 sockets::instance_network::add_to_linker::<T, WasiSockets>(l, T::sockets)?;
364 sockets::network::add_to_linker::<T, WasiSockets>(l, &options.into(), T::sockets)?;
365 sockets::ip_name_lookup::add_to_linker::<T, WasiSockets>(l, T::sockets)?;
366 Ok(())
367 }
368
369 /// Same as [`add_to_linker_async`] except that this only adds interfaces
370 /// present in the `wasi:http/proxy` world.
add_to_linker_proxy_interfaces_async<T: WasiView>( linker: &mut Linker<T>, ) -> wasmtime::Result<()>371 pub fn add_to_linker_proxy_interfaces_async<T: WasiView>(
372 linker: &mut Linker<T>,
373 ) -> wasmtime::Result<()> {
374 add_async_io_to_linker(linker)?;
375 add_proxy_interfaces_nonblocking(linker)
376 }
377
378 /// Same as [`add_to_linker_sync`] except that this only adds interfaces
379 /// present in the `wasi:http/proxy` world.
380 #[doc(hidden)]
add_to_linker_proxy_interfaces_sync<T: WasiView>( linker: &mut Linker<T>, ) -> wasmtime::Result<()>381 pub fn add_to_linker_proxy_interfaces_sync<T: WasiView>(
382 linker: &mut Linker<T>,
383 ) -> wasmtime::Result<()> {
384 add_sync_wasi_io(linker)?;
385 add_proxy_interfaces_nonblocking(linker)
386 }
387
add_proxy_interfaces_nonblocking<T: WasiView>(linker: &mut Linker<T>) -> wasmtime::Result<()>388 fn add_proxy_interfaces_nonblocking<T: WasiView>(linker: &mut Linker<T>) -> wasmtime::Result<()> {
389 use crate::p2::bindings::{cli, clocks, random};
390
391 let l = linker;
392 clocks::wall_clock::add_to_linker::<T, WasiClocks>(l, T::clocks)?;
393 clocks::monotonic_clock::add_to_linker::<T, WasiClocks>(l, T::clocks)?;
394 random::random::add_to_linker::<T, WasiRandom>(l, |t| &mut t.ctx().ctx.random)?;
395 cli::stdin::add_to_linker::<T, WasiCli>(l, T::cli)?;
396 cli::stdout::add_to_linker::<T, WasiCli>(l, T::cli)?;
397 cli::stderr::add_to_linker::<T, WasiCli>(l, T::cli)?;
398 Ok(())
399 }
400
401 /// Add all WASI interfaces from this crate into the `linker` provided.
402 ///
403 /// This function will add the synchronous variant of all interfaces into the
404 /// [`Linker`] provided. For embeddings with async support enabled see
405 /// [`add_to_linker_async`] instead.
406 ///
407 /// This function will add all interfaces implemented by this crate to the
408 /// [`Linker`], which corresponds to the `wasi:cli/imports` world supported by
409 /// this crate.
410 ///
411 /// # Example
412 ///
413 /// ```
414 /// use wasmtime::{Engine, Result, Store, Config};
415 /// use wasmtime::component::{ResourceTable, Linker};
416 /// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
417 ///
418 /// fn main() -> Result<()> {
419 /// let engine = Engine::default();
420 ///
421 /// let mut linker = Linker::<MyState>::new(&engine);
422 /// wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
423 /// // ... add any further functionality to `linker` if desired ...
424 ///
425 /// let mut builder = WasiCtx::builder();
426 ///
427 /// // ... configure `builder` more to add env vars, args, etc ...
428 ///
429 /// let mut store = Store::new(
430 /// &engine,
431 /// MyState {
432 /// ctx: builder.build(),
433 /// table: ResourceTable::new(),
434 /// },
435 /// );
436 ///
437 /// // ... use `linker` to instantiate within `store` ...
438 ///
439 /// Ok(())
440 /// }
441 ///
442 /// struct MyState {
443 /// ctx: WasiCtx,
444 /// table: ResourceTable,
445 /// }
446 /// impl WasiView for MyState {
447 /// fn ctx(&mut self) -> WasiCtxView<'_> {
448 /// WasiCtxView { ctx: &mut self.ctx, table: &mut self.table }
449 /// }
450 /// }
451 /// ```
add_to_linker_sync<T: WasiView>( linker: &mut wasmtime::component::Linker<T>, ) -> wasmtime::Result<()>452 pub fn add_to_linker_sync<T: WasiView>(
453 linker: &mut wasmtime::component::Linker<T>,
454 ) -> wasmtime::Result<()> {
455 let options = bindings::sync::LinkOptions::default();
456 add_to_linker_with_options_sync(linker, &options)
457 }
458
459 /// Similar to [`add_to_linker_sync`], but with the ability to enable unstable features.
add_to_linker_with_options_sync<T: WasiView>( linker: &mut wasmtime::component::Linker<T>, options: &bindings::sync::LinkOptions, ) -> wasmtime::Result<()>460 pub fn add_to_linker_with_options_sync<T: WasiView>(
461 linker: &mut wasmtime::component::Linker<T>,
462 options: &bindings::sync::LinkOptions,
463 ) -> wasmtime::Result<()> {
464 add_nonblocking_to_linker(linker, options)?;
465 add_sync_wasi_io(linker)?;
466
467 let l = linker;
468 bindings::sync::filesystem::types::add_to_linker::<T, WasiFilesystem>(l, T::filesystem)?;
469 bindings::sync::sockets::tcp::add_to_linker::<T, WasiSockets>(l, T::sockets)?;
470 bindings::sync::sockets::udp::add_to_linker::<T, WasiSockets>(l, T::sockets)?;
471 Ok(())
472 }
473
474 /// Shared functionality of [`add_to_linker_sync`]` and
475 /// [`add_to_linker_proxy_interfaces_sync`].
add_sync_wasi_io<T: WasiView>( linker: &mut wasmtime::component::Linker<T>, ) -> wasmtime::Result<()>476 fn add_sync_wasi_io<T: WasiView>(
477 linker: &mut wasmtime::component::Linker<T>,
478 ) -> wasmtime::Result<()> {
479 let l = linker;
480 wasmtime_wasi_io::bindings::wasi::io::error::add_to_linker::<T, HasIo>(l, |t| t.ctx().table)?;
481 bindings::sync::io::poll::add_to_linker::<T, HasIo>(l, |t| t.ctx().table)?;
482 bindings::sync::io::streams::add_to_linker::<T, HasIo>(l, |t| t.ctx().table)?;
483 Ok(())
484 }
485
486 struct HasIo;
487
488 impl HasData for HasIo {
489 type Data<'a> = &'a mut ResourceTable;
490 }
491
492 // FIXME: it's a bit unfortunate that this can't use
493 // `wasmtime_wasi_io::add_to_linker` and that's because `T: WasiView`, here,
494 // not `T: IoView`. Ideally we'd have `impl<T: WasiView> IoView for T` but
495 // that's not possible with these two traits in separate crates. For now this
496 // is some small duplication but if this gets worse over time then we'll want
497 // to massage this.
add_async_io_to_linker<T: WasiView>(l: &mut Linker<T>) -> wasmtime::Result<()>498 fn add_async_io_to_linker<T: WasiView>(l: &mut Linker<T>) -> wasmtime::Result<()> {
499 wasmtime_wasi_io::bindings::wasi::io::error::add_to_linker::<T, HasIo>(l, |t| t.ctx().table)?;
500 wasmtime_wasi_io::bindings::wasi::io::poll::add_to_linker::<T, HasIo>(l, |t| t.ctx().table)?;
501 wasmtime_wasi_io::bindings::wasi::io::streams::add_to_linker::<T, HasIo>(l, |t| t.ctx().table)?;
502 Ok(())
503 }
504