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;