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