xref: /wasmtime-44.0.1/crates/wasi-io/src/lib.rs (revision cc8d04f4)
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