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
22 extern crate alloc;
23 #[cfg(feature = "std")]
24 #[macro_use]
25 extern crate std;
26
27 pub mod bindings;
28 mod impls;
29 pub mod poll;
30 pub mod streams;
31
32 #[doc(no_inline)]
33 pub use async_trait::async_trait;
34
35 #[doc(no_inline)]
36 pub use ::bytes;
37
38 use alloc::boxed::Box;
39 use wasmtime::component::{HasData, 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::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 engine = Engine::default();
65 /// let mut linker: Linker<MyState> = Linker::new(&engine);
66 /// add_to_linker_async(&mut linker).unwrap();
67 /// ```
68 /// [`Store`]: wasmtime::Store
69 /// [`Linker`]: wasmtime::component::Linker
70 /// [`ResourceTable`]: wasmtime::component::ResourceTable
71 ///
72 pub trait IoView {
73 /// Yields mutable access to the internal resource management that this
74 /// context contains.
75 ///
76 /// Embedders can add custom resources to this table as well to give
77 /// resources to wasm as well.
table(&mut self) -> &mut ResourceTable78 fn table(&mut self) -> &mut ResourceTable;
79 }
80
81 impl<T: ?Sized + IoView> IoView for &mut T {
table(&mut self) -> &mut ResourceTable82 fn table(&mut self) -> &mut ResourceTable {
83 T::table(self)
84 }
85 }
86 impl<T: ?Sized + IoView> IoView for Box<T> {
table(&mut self) -> &mut ResourceTable87 fn table(&mut self) -> &mut ResourceTable {
88 T::table(self)
89 }
90 }
91
92 /// Add the wasi-io host implementation from this crate into the `linker`
93 /// provided.
94 ///
95 /// This function will add the `async` variant of all interfaces into the
96 /// [`Linker`] provided. For embeddings which don't want to use async, you'll
97 /// need to use other crates, such as the [`wasmtime-wasi`] crate, which
98 /// provides an [`add_to_linker_sync`] that includes an appropriate wasi-io
99 /// implementation based on this crate's.
100 ///
101 /// This function will add all interfaces implemented by this crate to the
102 /// [`Linker`], which corresponds to the `wasi:io/imports` world supported by
103 /// this crate.
104 ///
105 /// [`Linker`]: wasmtime::component::Linker
106 /// [`wasmtime-wasi`]: https://crates.io/crates/wasmtime-wasi
107 /// [`add_to_linker_sync`]: https://docs.rs/wasmtime-wasi/latest/wasmtime_wasi/p2/fn.add_to_linker_sync.html
108 ///
109 ///
110 /// # Example
111 ///
112 /// ```
113 /// use wasmtime::{Engine, Result, Store};
114 /// use wasmtime::component::{ResourceTable, Linker};
115 /// use wasmtime_wasi_io::IoView;
116 ///
117 /// fn main() -> Result<()> {
118 /// let engine = Engine::default();
119 ///
120 /// let mut linker = Linker::<MyState>::new(&engine);
121 /// wasmtime_wasi_io::add_to_linker_async(&mut linker)?;
122 /// // ... add any further functionality to `linker` if desired ...
123 ///
124 /// let mut store = Store::new(
125 /// &engine,
126 /// MyState {
127 /// table: ResourceTable::new(),
128 /// },
129 /// );
130 ///
131 /// // ... use `linker` to instantiate within `store` ...
132 ///
133 /// Ok(())
134 /// }
135 ///
136 /// struct MyState {
137 /// table: ResourceTable,
138 /// }
139 ///
140 /// impl IoView for MyState {
141 /// fn table(&mut self) -> &mut ResourceTable { &mut self.table }
142 /// }
143 /// ```
add_to_linker_async<T: IoView + Send + 'static>( l: &mut wasmtime::component::Linker<T>, ) -> wasmtime::Result<()>144 pub fn add_to_linker_async<T: IoView + Send + 'static>(
145 l: &mut wasmtime::component::Linker<T>,
146 ) -> wasmtime::Result<()> {
147 crate::bindings::wasi::io::error::add_to_linker::<T, WasiIo>(l, T::table)?;
148 crate::bindings::wasi::io::poll::add_to_linker::<T, WasiIo>(l, T::table)?;
149 crate::bindings::wasi::io::streams::add_to_linker::<T, WasiIo>(l, T::table)?;
150 Ok(())
151 }
152
153 struct WasiIo;
154
155 impl HasData for WasiIo {
156 type Data<'a> = &'a mut ResourceTable;
157 }
158