wasmtime_wasi/p2/
bindings.rs

1//! Auto-generated bindings for WASI interfaces.
2//!
3//! This module contains the output of the [`bindgen!`] macro when run over
4//! the `wasi:cli/command` world. That means this module has all the generated
5//! types for WASI for all of its base interfaces used by the CLI world. This
6//! module itself by default contains bindings for `async`-related traits. The
7//! [`sync`] module contains bindings for a non-`async` version of types.
8//!
9//! [`bindgen!`]: https://docs.rs/wasmtime/latest/wasmtime/component/macro.bindgen.html
10//!
11//! # Examples
12//!
13//! If you have a WIT world which refers to WASI interfaces you probably want to
14//! use this modules's bindings rather than generate fresh bindings. That can be
15//! done using the `with` option to [`bindgen!`]:
16//!
17//! ```rust
18//! use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
19//! use wasmtime::{Result, Engine, Config};
20//! use wasmtime::component::{Linker, ResourceTable, HasSelf};
21//!
22//! wasmtime::component::bindgen!({
23//!     inline: "
24//!         package example:wasi;
25//!
26//!         // An example of extending the `wasi:cli/command` world with a
27//!         // custom host interface.
28//!         world my-world {
29//!             include wasi:cli/command@0.2.6;
30//!
31//!             import custom-host;
32//!         }
33//!
34//!         interface custom-host {
35//!             my-custom-function: func();
36//!         }
37//!     ",
38//!     path: "src/p2/wit",
39//!     with: {
40//!         "wasi": wasmtime_wasi::p2::bindings,
41//!     },
42//!     imports: { default: async },
43//! });
44//!
45//! struct MyState {
46//!     table: ResourceTable,
47//!     ctx: WasiCtx,
48//! }
49//!
50//! impl example::wasi::custom_host::Host for MyState {
51//!     async fn my_custom_function(&mut self) {
52//!         // ..
53//!     }
54//! }
55//!
56//! impl WasiView for MyState {
57//!     fn ctx(&mut self) -> WasiCtxView<'_> {
58//!         WasiCtxView { ctx: &mut self.ctx, table: &mut self.table }
59//!     }
60//! }
61//!
62//! fn main() -> Result<()> {
63//!     let mut config = Config::default();
64//!     config.async_support(true);
65//!     let engine = Engine::new(&config)?;
66//!     let mut linker: Linker<MyState> = Linker::new(&engine);
67//!     wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
68//!     example::wasi::custom_host::add_to_linker::<_, HasSelf<_>>(&mut linker, |state| state)?;
69//!
70//!     // .. use `Linker` to instantiate component ...
71//!
72//!     Ok(())
73//! }
74//! ```
75
76/// Synchronous-generated bindings for WASI interfaces.
77///
78/// This is the same as the top-level [`bindings`](crate::p2::bindings) submodule of
79/// this module except that it's for synchronous calls.
80///
81/// # Examples
82///
83/// If you have a WIT world which refers to WASI interfaces you probably want to
84/// use this modules's bindings rather than generate fresh bindings. That can be
85/// done using the `with` option to `bindgen!`:
86///
87/// ```rust
88/// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
89/// use wasmtime::{Result, Engine};
90/// use wasmtime::component::{Linker, ResourceTable, HasSelf};
91///
92/// wasmtime::component::bindgen!({
93///     inline: "
94///         package example:wasi;
95///
96///         // An example of extending the `wasi:cli/command` world with a
97///         // custom host interface.
98///         world my-world {
99///             include wasi:cli/command@0.2.6;
100///
101///             import custom-host;
102///         }
103///
104///         interface custom-host {
105///             my-custom-function: func();
106///         }
107///     ",
108///     path: "src/p2/wit",
109///     with: {
110///         "wasi": wasmtime_wasi::p2::bindings::sync,
111///     },
112///     // This is required for bindings using `wasmtime-wasi` and it otherwise
113///     // isn't the default for non-async bindings.
114///     require_store_data_send: true,
115/// });
116///
117/// struct MyState {
118///     table: ResourceTable,
119///     ctx: WasiCtx,
120/// }
121///
122/// impl example::wasi::custom_host::Host for MyState {
123///     fn my_custom_function(&mut self) {
124///         // ..
125///     }
126/// }
127///
128/// impl WasiView for MyState {
129///     fn ctx(&mut self) -> WasiCtxView<'_> {
130///         WasiCtxView { ctx: &mut self.ctx, table: &mut self.table }
131///     }
132/// }
133///
134/// fn main() -> Result<()> {
135///     let engine = Engine::default();
136///     let mut linker: Linker<MyState> = Linker::new(&engine);
137///     wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
138///     example::wasi::custom_host::add_to_linker::<_, HasSelf<_>>(&mut linker, |state| state)?;
139///
140///     // .. use `Linker` to instantiate component ...
141///
142///     Ok(())
143/// }
144/// ```
145pub mod sync {
146    mod generated {
147        use crate::p2::{FsError, SocketError};
148        use wasmtime_wasi_io::streams::StreamError;
149
150        wasmtime::component::bindgen!({
151            path: "src/p2/wit",
152            world: "wasi:cli/command",
153            trappable_error_type: {
154                "wasi:io/streams/stream-error" => StreamError,
155                "wasi:filesystem/types/error-code" => FsError,
156                "wasi:sockets/network/error-code" => SocketError,
157            },
158            imports: { default: tracing | trappable },
159            with: {
160                // These interfaces contain only synchronous methods, so they
161                // can be aliased directly
162                "wasi:clocks": crate::p2::bindings::clocks,
163                "wasi:random": crate::p2::bindings::random,
164                "wasi:cli": crate::p2::bindings::cli,
165                "wasi:filesystem/preopens": crate::p2::bindings::filesystem::preopens,
166                "wasi:sockets/network": crate::p2::bindings::sockets::network,
167
168                // Configure the resource types of the bound interfaces here
169                // to be the same as the async versions of the resources, that
170                // way everything has the same type.
171                "wasi:filesystem/types/descriptor": crate::filesystem::Descriptor,
172                "wasi:filesystem/types/directory-entry-stream": super::super::filesystem::types::DirectoryEntryStream,
173                "wasi:sockets/tcp/tcp-socket": super::super::sockets::tcp::TcpSocket,
174                "wasi:sockets/udp/incoming-datagram-stream": super::super::sockets::udp::IncomingDatagramStream,
175                "wasi:sockets/udp/outgoing-datagram-stream": super::super::sockets::udp::OutgoingDatagramStream,
176                "wasi:sockets/udp/udp-socket": crate::sockets::UdpSocket,
177
178                // Error host trait from wasmtime-wasi-io is synchronous, so we can alias it
179                "wasi:io/error": wasmtime_wasi_io::bindings::wasi::io::error,
180                // Configure the resource types from wasmtime-wasi-io, though
181                // this bindgen will make a new synchronous Host traits
182                "wasi:io/poll/pollable": wasmtime_wasi_io::poll::DynPollable,
183                "wasi:io/streams/input-stream": wasmtime_wasi_io::streams::DynInputStream,
184                "wasi:io/streams/output-stream": wasmtime_wasi_io::streams::DynOutputStream,
185
186            },
187            require_store_data_send: true,
188        });
189    }
190    pub use self::generated::exports;
191    pub use self::generated::wasi::*;
192
193    /// Synchronous bindings to execute and run a `wasi:cli/command`.
194    ///
195    /// This structure is automatically generated by `bindgen!` and is intended
196    /// to be used with [`Config::async_support(false)`][async]. For the
197    /// asynchronous version see [`bindings::Command`](super::Command).
198    ///
199    /// This can be used for a more "typed" view of executing a command
200    /// component through the [`Command::wasi_cli_run`] method plus
201    /// [`Guest::call_run`](exports::wasi::cli::run::Guest::call_run).
202    ///
203    /// [async]: wasmtime::Config::async_support
204    /// [`wasmtime_wasi::p2::add_to_linker_sync`]: crate::p2::add_to_linker_sync
205    ///
206    /// # Examples
207    ///
208    /// ```no_run
209    /// use wasmtime::{Engine, Result, Store, Config};
210    /// use wasmtime::component::{ResourceTable, Linker, Component};
211    /// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
212    /// use wasmtime_wasi::p2::bindings::sync::Command;
213    ///
214    /// // This example is an example shim of executing a component based on the
215    /// // command line arguments provided to this program.
216    /// fn main() -> Result<()> {
217    ///     let args = std::env::args().skip(1).collect::<Vec<_>>();
218    ///
219    ///     // Configure and create `Engine`
220    ///     let engine = Engine::default();
221    ///
222    ///     // Configure a `Linker` with WASI, compile a component based on
223    ///     // command line arguments.
224    ///     let mut linker = Linker::<MyState>::new(&engine);
225    ///     wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
226    ///     let component = Component::from_file(&engine, &args[0])?;
227    ///
228    ///
229    ///     // Configure a `WasiCtx` based on this program's environment. Then
230    ///     // build a `Store` to instantiate into.
231    ///     let mut builder = WasiCtx::builder();
232    ///     builder.inherit_stdio().inherit_env().args(&args[2..]);
233    ///     let mut store = Store::new(
234    ///         &engine,
235    ///         MyState {
236    ///             ctx: builder.build(),
237    ///             table: ResourceTable::new(),
238    ///         },
239    ///     );
240    ///
241    ///     // Instantiate the component and we're off to the races.
242    ///     let command = Command::instantiate(&mut store, &component, &linker)?;
243    ///     let program_result = command.wasi_cli_run().call_run(&mut store)?;
244    ///     match program_result {
245    ///         Ok(()) => Ok(()),
246    ///         Err(()) => std::process::exit(1),
247    ///     }
248    /// }
249    ///
250    /// struct MyState {
251    ///     ctx: WasiCtx,
252    ///     table: ResourceTable,
253    /// }
254    ///
255    /// impl WasiView for MyState {
256    ///     fn ctx(&mut self) -> WasiCtxView<'_> {
257    ///         WasiCtxView { ctx: &mut self.ctx, table: &mut self.table }
258    ///     }
259    /// }
260    /// ```
261    ///
262    /// ---
263    pub use self::generated::Command;
264
265    /// Pre-instantiated analogue of [`Command`].
266    ///
267    /// This works the same as [`Command`] but enables front-loading work such
268    /// as export lookup to before instantiation.
269    ///
270    /// # Examples
271    ///
272    /// ```no_run
273    /// use wasmtime::{Engine, Result, Store, Config};
274    /// use wasmtime::component::{ResourceTable, Linker, Component};
275    /// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
276    /// use wasmtime_wasi::p2::bindings::sync::CommandPre;
277    ///
278    /// // This example is an example shim of executing a component based on the
279    /// // command line arguments provided to this program.
280    /// fn main() -> Result<()> {
281    ///     let args = std::env::args().skip(1).collect::<Vec<_>>();
282    ///
283    ///     // Configure and create `Engine`
284    ///     let engine = Engine::default();
285    ///
286    ///     // Configure a `Linker` with WASI, compile a component based on
287    ///     // command line arguments, and then pre-instantiate it.
288    ///     let mut linker = Linker::<MyState>::new(&engine);
289    ///     wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
290    ///     let component = Component::from_file(&engine, &args[0])?;
291    ///     let pre = CommandPre::new(linker.instantiate_pre(&component)?)?;
292    ///
293    ///
294    ///     // Configure a `WasiCtx` based on this program's environment. Then
295    ///     // build a `Store` to instantiate into.
296    ///     let mut builder = WasiCtx::builder();
297    ///     builder.inherit_stdio().inherit_env().args(&args);
298    ///     let mut store = Store::new(
299    ///         &engine,
300    ///         MyState {
301    ///             ctx: builder.build(),
302    ///             table: ResourceTable::new(),
303    ///         },
304    ///     );
305    ///
306    ///     // Instantiate the component and we're off to the races.
307    ///     let command = pre.instantiate(&mut store)?;
308    ///     let program_result = command.wasi_cli_run().call_run(&mut store)?;
309    ///     match program_result {
310    ///         Ok(()) => Ok(()),
311    ///         Err(()) => std::process::exit(1),
312    ///     }
313    /// }
314    ///
315    /// struct MyState {
316    ///     ctx: WasiCtx,
317    ///     table: ResourceTable,
318    /// }
319    ///
320    /// impl WasiView for MyState {
321    ///     fn ctx(&mut self) -> WasiCtxView<'_> {
322    ///         WasiCtxView { ctx: &mut self.ctx, table: &mut self.table }
323    ///     }
324    /// }
325    /// ```
326    ///
327    /// ---
328    pub use self::generated::CommandPre;
329
330    pub use self::generated::CommandIndices;
331
332    pub use self::generated::LinkOptions;
333}
334
335mod async_io {
336    wasmtime::component::bindgen!({
337        path: "src/p2/wit",
338        world: "wasi:cli/command",
339        imports: {
340            // Only these functions are `async` and everything else is sync
341            // meaning that it basically doesn't need to block. These functions
342            // are the only ones that need to block.
343            //
344            // Note that at this time `only_imports` works on function names
345            // which in theory can be shared across interfaces, so this may
346            // need fancier syntax in the future.
347            "wasi:filesystem/types/[method]descriptor.advise": async | tracing | trappable,
348            "wasi:filesystem/types/[method]descriptor.create-directory-at": async | tracing | trappable,
349            "wasi:filesystem/types/[method]descriptor.get-flags": async | tracing | trappable,
350            "wasi:filesystem/types/[method]descriptor.get-type": async | tracing | trappable,
351            "wasi:filesystem/types/[method]descriptor.is-same-object": async | tracing | trappable,
352            "wasi:filesystem/types/[method]descriptor.link-at": async | tracing | trappable,
353            "wasi:filesystem/types/[method]descriptor.metadata-hash": async | tracing | trappable,
354            "wasi:filesystem/types/[method]descriptor.metadata-hash-at": async | tracing | trappable,
355            "wasi:filesystem/types/[method]descriptor.open-at": async | tracing | trappable,
356            "wasi:filesystem/types/[method]descriptor.read": async | tracing | trappable,
357            "wasi:filesystem/types/[method]descriptor.read-directory": async | tracing | trappable,
358            "wasi:filesystem/types/[method]descriptor.readlink-at": async | tracing | trappable,
359            "wasi:filesystem/types/[method]descriptor.remove-directory-at": async | tracing | trappable,
360            "wasi:filesystem/types/[method]descriptor.rename-at": async | tracing | trappable,
361            "wasi:filesystem/types/[method]descriptor.set-size": async | tracing | trappable,
362            "wasi:filesystem/types/[method]descriptor.set-times": async | tracing | trappable,
363            "wasi:filesystem/types/[method]descriptor.set-times-at": async | tracing | trappable,
364            "wasi:filesystem/types/[method]descriptor.stat": async | tracing | trappable,
365            "wasi:filesystem/types/[method]descriptor.stat-at": async | tracing | trappable,
366            "wasi:filesystem/types/[method]descriptor.symlink-at": async | tracing | trappable,
367            "wasi:filesystem/types/[method]descriptor.sync": async | tracing | trappable,
368            "wasi:filesystem/types/[method]descriptor.sync-data": async | tracing | trappable,
369            "wasi:filesystem/types/[method]descriptor.unlink-file-at": async | tracing | trappable,
370            "wasi:filesystem/types/[method]descriptor.write": async | tracing | trappable,
371            "wasi:filesystem/types/[method]directory-entry-stream.read-directory-entry": async | tracing | trappable,
372            "wasi:sockets/tcp/[method]tcp-socket.start-bind": async | tracing | trappable,
373            "wasi:sockets/tcp/[method]tcp-socket.start-connect": async | tracing | trappable,
374            "wasi:sockets/udp/[method]udp-socket.start-bind": async | tracing | trappable,
375            "wasi:sockets/udp/[method]udp-socket.stream": async | tracing | trappable,
376            "wasi:sockets/udp/[method]outgoing-datagram-stream.send": async | tracing | trappable,
377            default: tracing | trappable,
378        },
379        exports: { default: async },
380        trappable_error_type: {
381            "wasi:io/streams/stream-error" => wasmtime_wasi_io::streams::StreamError,
382            "wasi:filesystem/types/error-code" => crate::p2::FsError,
383            "wasi:sockets/network/error-code" => crate::p2::SocketError,
384        },
385        with: {
386            // All interfaces in the wasi:io package should be aliased to
387            // the wasmtime-wasi-io generated code. Note that this will also
388            // map the resource types to those defined in that crate as well.
389            "wasi:io/poll": wasmtime_wasi_io::bindings::wasi::io::poll,
390            "wasi:io/streams": wasmtime_wasi_io::bindings::wasi::io::streams,
391            "wasi:io/error": wasmtime_wasi_io::bindings::wasi::io::error,
392
393            // Configure all other resources to be concrete types defined in
394            // this crate
395            "wasi:sockets/network/network": crate::p2::network::Network,
396            "wasi:sockets/tcp/tcp-socket": crate::sockets::TcpSocket,
397            "wasi:sockets/udp/udp-socket": crate::sockets::UdpSocket,
398            "wasi:sockets/udp/incoming-datagram-stream": crate::p2::udp::IncomingDatagramStream,
399            "wasi:sockets/udp/outgoing-datagram-stream": crate::p2::udp::OutgoingDatagramStream,
400            "wasi:sockets/ip-name-lookup/resolve-address-stream": crate::p2::ip_name_lookup::ResolveAddressStream,
401            "wasi:filesystem/types/directory-entry-stream": crate::p2::filesystem::ReaddirIterator,
402            "wasi:filesystem/types/descriptor": crate::filesystem::Descriptor,
403            "wasi:cli/terminal-input/terminal-input": crate::p2::stdio::TerminalInput,
404            "wasi:cli/terminal-output/terminal-output": crate::p2::stdio::TerminalOutput,
405        },
406    });
407}
408
409pub use self::async_io::LinkOptions;
410pub use self::async_io::exports;
411pub use self::async_io::wasi::*;
412
413/// Asynchronous bindings to execute and run a `wasi:cli/command`.
414///
415/// This structure is automatically generated by `bindgen!` and is intended to
416/// be used with [`Config::async_support(true)`][async]. For the synchronous
417/// version see [`bindings::sync::Command`](sync::Command).
418///
419/// This can be used for a more "typed" view of executing a command component
420/// through the [`Command::wasi_cli_run`] method plus
421/// [`Guest::call_run`](exports::wasi::cli::run::Guest::call_run).
422///
423/// [async]: wasmtime::Config::async_support
424/// [`wasmtime_wasi::p2::add_to_linker_async`]: crate::p2::add_to_linker_async
425///
426/// # Examples
427///
428/// ```no_run
429/// use wasmtime::{Engine, Result, Store, Config};
430/// use wasmtime::component::{ResourceTable, Linker, Component};
431/// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
432/// use wasmtime_wasi::p2::bindings::Command;
433///
434/// // This example is an example shim of executing a component based on the
435/// // command line arguments provided to this program.
436/// #[tokio::main]
437/// async fn main() -> Result<()> {
438///     let args = std::env::args().skip(1).collect::<Vec<_>>();
439///
440///     // Configure and create `Engine`
441///     let mut config = Config::new();
442///     config.async_support(true);
443///     let engine = Engine::new(&config)?;
444///
445///     // Configure a `Linker` with WASI, compile a component based on
446///     // command line arguments, and then pre-instantiate it.
447///     let mut linker = Linker::<MyState>::new(&engine);
448///     wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
449///     let component = Component::from_file(&engine, &args[0])?;
450///
451///
452///     // Configure a `WasiCtx` based on this program's environment. Then
453///     // build a `Store` to instantiate into.
454///     let mut builder = WasiCtx::builder();
455///     builder.inherit_stdio().inherit_env().args(&args);
456///     let mut store = Store::new(
457///         &engine,
458///         MyState {
459///             ctx: builder.build(),
460///             table: ResourceTable::new(),
461///         },
462///     );
463///
464///     // Instantiate the component and we're off to the races.
465///     let command = Command::instantiate_async(&mut store, &component, &linker).await?;
466///     let program_result = command.wasi_cli_run().call_run(&mut store).await?;
467///     match program_result {
468///         Ok(()) => Ok(()),
469///         Err(()) => std::process::exit(1),
470///     }
471/// }
472///
473/// struct MyState {
474///     ctx: WasiCtx,
475///     table: ResourceTable,
476/// }
477///
478/// impl WasiView for MyState {
479///     fn ctx(&mut self) -> WasiCtxView<'_> {
480///         WasiCtxView { ctx: &mut self.ctx, table: &mut self.table }
481///     }
482/// }
483/// ```
484///
485/// ---
486pub use self::async_io::Command;
487
488/// Pre-instantiated analog of [`Command`]
489///
490/// This can be used to front-load work such as export lookup before
491/// instantiation.
492///
493/// # Examples
494///
495/// ```no_run
496/// use wasmtime::{Engine, Result, Store, Config};
497/// use wasmtime::component::{ResourceTable, Linker, Component};
498/// use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
499/// use wasmtime_wasi::p2::bindings::CommandPre;
500///
501/// // This example is an example shim of executing a component based on the
502/// // command line arguments provided to this program.
503/// #[tokio::main]
504/// async fn main() -> Result<()> {
505///     let args = std::env::args().skip(1).collect::<Vec<_>>();
506///
507///     // Configure and create `Engine`
508///     let mut config = Config::new();
509///     config.async_support(true);
510///     let engine = Engine::new(&config)?;
511///
512///     // Configure a `Linker` with WASI, compile a component based on
513///     // command line arguments, and then pre-instantiate it.
514///     let mut linker = Linker::<MyState>::new(&engine);
515///     wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
516///     let component = Component::from_file(&engine, &args[0])?;
517///     let pre = CommandPre::new(linker.instantiate_pre(&component)?)?;
518///
519///
520///     // Configure a `WasiCtx` based on this program's environment. Then
521///     // build a `Store` to instantiate into.
522///     let mut builder = WasiCtx::builder();
523///     builder.inherit_stdio().inherit_env().args(&args);
524///     let mut store = Store::new(
525///         &engine,
526///         MyState {
527///             ctx: builder.build(),
528///             table: ResourceTable::new(),
529///         },
530///     );
531///
532///     // Instantiate the component and we're off to the races.
533///     let command = pre.instantiate_async(&mut store).await?;
534///     let program_result = command.wasi_cli_run().call_run(&mut store).await?;
535///     match program_result {
536///         Ok(()) => Ok(()),
537///         Err(()) => std::process::exit(1),
538///     }
539/// }
540///
541/// struct MyState {
542///     ctx: WasiCtx,
543///     table: ResourceTable,
544/// }
545///
546/// impl WasiView for MyState {
547///     fn ctx(&mut self) -> WasiCtxView<'_> {
548///         WasiCtxView { ctx: &mut self.ctx, table: &mut self.table }
549///     }
550/// }
551/// ```
552///
553/// ---
554pub use self::async_io::CommandPre;
555
556pub use self::async_io::CommandIndices;