wasmtime_wasi_io/lib.rs
1//! # Wasmtime's wasi-io Implementation
2//!
3//! This crate provides a Wasmtime host implementation of the WASI 0.2 (aka
4//! WASIp2 aka Preview 2) wasi-io package. The host implementation is
5//! abstract: it is exposed as a set of traits which other crates provide
6//! impls of.
7//!
8//! The wasi-io package is the foundation which defines how WASI programs
9//! interact with the scheduler. It provides the `pollable`, `input-stream`,
10//! and `output-stream` Component Model resources, which other packages
11//! (including wasi-filesystem, wasi-sockets, wasi-cli, and wasi-http)
12//! expose as the standard way to wait for readiness, and asynchronously read
13//! and write to streams.
14//!
15//! This crate is designed to have no unnecessary dependencies and, in
16//! particular, to be #![no_std]. For an example no_std embedding, see
17//! [`/examples/min-platform`](https://github.com/bytecodealliance/wasmtime/tree/main/examples/min-platform)
18//! at the root of the wasmtime repo.
19
20#![no_std]
21
22extern crate alloc;
23#[cfg(feature = "std")]
24#[macro_use]
25extern crate std;
26
27pub mod bindings;
28mod impls;
29pub mod poll;
30pub mod streams;
31
32#[doc(no_inline)]
33pub use async_trait::async_trait;
34
35#[doc(no_inline)]
36pub use ::bytes;
37
38use alloc::boxed::Box;
39use wasmtime::component::ResourceTable;
40
41/// A trait which provides access to the [`ResourceTable`] inside the
42/// embedder's `T` of [`Store<T>`][`Store`].
43///
44/// This crate's WASI Host implementations depend on the contents of
45/// [`ResourceTable`]. The `T` type [`Store<T>`][`Store`] is defined in each
46/// embedding of Wasmtime. These implementations is connected to the
47/// [`Linker<T>`][`Linker`] by the
48/// [`add_to_linker_async`] function.
49///
50/// # Example
51///
52/// ```
53/// use wasmtime::{Config, Engine};
54/// use wasmtime::component::{ResourceTable, Linker};
55/// use wasmtime_wasi_io::{IoView, add_to_linker_async};
56///
57/// struct MyState {
58/// table: ResourceTable,
59/// }
60///
61/// impl IoView for MyState {
62/// fn table(&mut self) -> &mut ResourceTable { &mut self.table }
63/// }
64/// let mut config = Config::new();
65/// config.async_support(true);
66/// let engine = Engine::new(&config).unwrap();
67/// let mut linker: Linker<MyState> = Linker::new(&engine);
68/// add_to_linker_async(&mut linker).unwrap();
69/// ```
70/// [`Store`]: wasmtime::Store
71/// [`Linker`]: wasmtime::component::Linker
72/// [`ResourceTable`]: wasmtime::component::ResourceTable
73///
74pub trait IoView: Send {
75 /// Yields mutable access to the internal resource management that this
76 /// context contains.
77 ///
78 /// Embedders can add custom resources to this table as well to give
79 /// resources to wasm as well.
80 fn table(&mut self) -> &mut ResourceTable;
81}
82impl<T: ?Sized + IoView> IoView for &mut T {
83 fn table(&mut self) -> &mut ResourceTable {
84 T::table(self)
85 }
86}
87impl<T: ?Sized + IoView> IoView for Box<T> {
88 fn table(&mut self) -> &mut ResourceTable {
89 T::table(self)
90 }
91}
92
93/// A small newtype wrapper which serves as the basis for implementations of
94/// `Host` WASI traits in this crate.
95///
96/// This type is used as the basis for the implementation of all `Host` traits
97/// generated by `bindgen!` for WASI interfaces.
98///
99/// You don't need to use this type if you are using the root
100/// [`add_to_linker_async`] in this crate.
101///
102/// If you're calling the `add_to_linker` functions generated by `bindgen!`
103/// from the [`bindings` module](crate::bindings), you'll want to create a
104/// value of this type in the closures added to a [`Linker`].
105///
106/// [`Linker`]: wasmtime::component::Linker
107#[repr(transparent)]
108pub struct IoImpl<T>(pub T);
109impl<T: IoView> IoView for IoImpl<T> {
110 fn table(&mut self) -> &mut ResourceTable {
111 T::table(&mut self.0)
112 }
113}
114
115/// Add the wasi-io host implementation from this crate into the `linker`
116/// provided.
117///
118/// This function will add the `async` variant of all interfaces into the
119/// [`Linker`] provided. By `async` this means that this function is only
120/// compatible with [`Config::async_support(true)`][async]. For embeddings
121/// with async support disabled, you'll need to use other crates, such as the
122/// [`wasmtime-wasi`] crate, which provides an [`add_to_linker_sync`] that
123/// includes an appropriate wasi-io implementation based on this crate's.
124///
125/// This function will add all interfaces implemented by this crate to the
126/// [`Linker`], which corresponds to the `wasi:io/imports` world supported by
127/// this crate.
128///
129/// [async]: wasmtime::Config::async_support
130/// [`Linker`]: wasmtime::component::Linker
131/// [`wasmtime-wasi`]: https://crates.io/crates/wasmtime-wasi
132/// [`add_to_linker_sync`]: https://docs.rs/wasmtime-wasi/latest/wasmtime_wasi/fn.add_to_linker_sync.html
133///
134///
135/// # Example
136///
137/// ```
138/// use wasmtime::{Engine, Result, Store, Config};
139/// use wasmtime::component::{ResourceTable, Linker};
140/// use wasmtime_wasi_io::IoView;
141///
142/// fn main() -> Result<()> {
143/// let mut config = Config::new();
144/// config.async_support(true);
145/// let engine = Engine::new(&config)?;
146///
147/// let mut linker = Linker::<MyState>::new(&engine);
148/// wasmtime_wasi_io::add_to_linker_async(&mut linker)?;
149/// // ... add any further functionality to `linker` if desired ...
150///
151/// let mut store = Store::new(
152/// &engine,
153/// MyState {
154/// table: ResourceTable::new(),
155/// },
156/// );
157///
158/// // ... use `linker` to instantiate within `store` ...
159///
160/// Ok(())
161/// }
162///
163/// struct MyState {
164/// table: ResourceTable,
165/// }
166///
167/// impl IoView for MyState {
168/// fn table(&mut self) -> &mut ResourceTable { &mut self.table }
169/// }
170/// ```
171pub fn add_to_linker_async<T: IoView>(
172 l: &mut wasmtime::component::Linker<T>,
173) -> wasmtime::Result<()> {
174 let closure = io_type_annotate::<T, _>(|t| IoImpl(t));
175 crate::bindings::wasi::io::error::add_to_linker_get_host(l, closure)?;
176 crate::bindings::wasi::io::poll::add_to_linker_get_host(l, closure)?;
177 crate::bindings::wasi::io::streams::add_to_linker_get_host(l, closure)?;
178 Ok(())
179}
180
181// NB: workaround some rustc inference - a future refactoring may make this
182// obsolete.
183fn io_type_annotate<T: IoView, F>(val: F) -> F
184where
185 F: Fn(&mut T) -> IoImpl<&mut T>,
186{
187 val
188}