wasmtime/runtime/component/bindgen_examples/
mod.rs

1//! Examples of output of the [`bindgen!`] macro.
2//!
3//! This module is only included in docs.rs documentation and is not present in
4//! the actual crate when compiling from crates.io. The purpose of this module
5//! is to showcase what the output of the [`bindgen!`] macro looks like and some
6//! examples of how to use it.
7//!
8//! If you're confused or lost in [`bindgen!`] feel free to [open an issue]
9//! with a description of your issue and it can hopefully lead to a new example
10//! being added here for others to use as reference.
11//!
12//! ## Including `*.wit` files in your project
13//!
14//! Note that most of the examples in this module will use the `inline` key of
15//! the [`bindgen!`] macro. This is done as it's easy to show the example and
16//! WIT all in one self-contained snippet of Rust code. Typically though a
17//! project will have a `wit` directory next to `Cargo.toml` which contains WIT
18//! files.
19//!
20//! The general layout of a `wit` directory is that:
21//!
22//! * All `*.wit` files at `wit/*.wit` are parsed and included in the same
23//!   package.
24//! * If the `wit/deps` folder is present then it can either contain:
25//!   * Subdirectories with a package-per-directory. For example
26//!     `wit/deps/wasi-http` and `wit/deps/wasi-cli`.
27//!   * WIT files that are a single-file rendering of a package, for example
28//!     `wit/deps/wasi-http.wit`
29//!   * WIT packages encoded as WebAssembly binaries for a package, for example
30//!     `wit/deps/wasi-http.wasm`
31//!
32//! This means that at this time you'll need to copy around `*.wit` files or
33//! WIT packages encoded as `*.wasm` and check them in to your project's `wit`
34//! directory. The hope is that in the future it will be easier to manage these
35//! files with registry tooling and they won't have to be copied manually.
36//! For reference documentation on the layout of the `wit` directory see
37//! [`wit_parser::Resolve::push_dir`].
38//!
39//! [`bindgen!`]: crate::component::bindgen
40//! [`wit_parser::Resolve::push_dir`]: https://docs.rs/wit-parser/latest/wit_parser/struct.Resolve.html#method.push_dir
41//! [open an issue]: https://github.com/bytecodealliance/wasmtime/issues/new
42
43#![allow(missing_docs)]
44
45// This "hack" will shadow the `bindgen` macro in general and be inherited to
46// following modules by default. This enables documenting sources as-is while
47// additionally customizing them to working within the wasmtime crate itself by
48// injecting a configuration option to change how the `wasmtime` crate is
49// referenced in the generated output.
50//
51// Note that this has an additional "hack" such that when docs.rs is documenting
52// this crate (or CI) then `include_generated_code_from_file` is unconditionally
53// turned on. This makes `[source]` links on documentation show the actual
54// generated code rather than just the `bindgen!` macro invocation, which can be
55// helpful when exploring code.
56#[cfg(docsrs)]
57macro_rules! bindgen {
58    ({$($t:tt)*}) => (crate::component::bindgen!({
59        $($t)*
60        wasmtime_crate: crate,
61        include_generated_code_from_file: true,
62    }););
63}
64#[cfg(not(docsrs))]
65macro_rules! bindgen {
66    ({$($t:tt)*}) => (crate::component::bindgen!({
67        $($t)*
68        wasmtime_crate: crate,
69    }););
70}
71
72/// A "hello world" style example.
73///
74/// This example loads a component which has access to a single host function.
75/// The exported function is called on an instantiation of the component.
76///
77/// ```rust
78/// use wasmtime::component::*;
79/// use wasmtime::{Engine, Store};
80///
81#[doc = include_str!("./_0_hello_world.rs")]
82///
83/// struct MyState {
84///     name: String,
85/// }
86///
87/// // Imports into the world, like the `name` import for this world, are
88/// // satisfied through traits.
89/// impl HelloWorldImports for MyState {
90///     fn name(&mut self) -> String {
91///         self.name.clone()
92///     }
93/// }
94///
95/// fn main() -> wasmtime::Result<()> {
96/// #   if true { return Ok(()) }
97///     // Compile the `Component` that is being run for the application.
98///     let engine = Engine::default();
99///     let component = Component::from_file(&engine, "./your-component.wasm")?;
100///
101///     // Instantiation of bindings always happens through a `Linker`.
102///     // Configuration of the linker is done through a generated `add_to_linker`
103///     // method on the bindings structure.
104///     //
105///     // Note that the function provided here is a projection from `T` in
106///     // `Store<T>` to `&mut U` where `U` implements the `HelloWorldImports`
107///     // trait. In this case the `T`, `MyState`, is stored directly in the
108///     // structure so no projection is necessary here.
109///     //
110///     // Note that the second type parameter of `add_to_linker` is chosen here
111///     // as the built-in `HasSelf` type in Wasmtime. This effectively says
112///     // that our function isn't actually projecting, it's returning the
113///     // input, so `HasSelf<_>` is a convenience to avoid writing a custom
114///     // `HasData` implementation.
115///     let mut linker = Linker::new(&engine);
116///     HelloWorld::add_to_linker::<_, HasSelf<_>>(&mut linker, |state| state)?;
117///
118///     // As with the core wasm API of Wasmtime instantiation occurs within a
119///     // `Store`. The bindings structure contains an `instantiate` method which
120///     // takes the store, component, and linker. This returns the `bindings`
121///     // structure which is an instance of `HelloWorld` and supports typed access
122///     // to the exports of the component.
123///     let mut store = Store::new(
124///         &engine,
125///         MyState {
126///             name: "me".to_string(),
127///         },
128///     );
129///     let bindings = HelloWorld::instantiate(&mut store, &component, &linker)?;
130///
131///     // Here our `greet` function doesn't take any parameters for the component,
132///     // but in the Wasmtime embedding API the first argument is always a `Store`.
133///     bindings.call_greet(&mut store)?;
134///     Ok(())
135/// }
136/// ```
137pub mod _0_hello_world;
138
139/// An example of generated bindings for top-level imported functions and
140/// interfaces into a world.
141///
142/// The code used to generate this module is:
143///
144/// ```rust
145/// use wasmtime::component::*;
146/// use wasmtime::{Engine, Store};
147///
148#[doc = include_str!("./_1_world_imports.rs")]
149///
150/// struct MyState {
151///     // ...
152/// }
153///
154/// impl my_custom_host::Host for MyState {
155///     fn tick(&mut self) {
156///         todo!()
157///     }
158/// }
159///
160/// impl MyWorldImports for MyState {
161///     fn greet(&mut self) -> String {
162///         todo!()
163///     }
164///
165///     fn log(&mut self, msg: String) {
166///         println!("{msg}");
167///     }
168/// }
169///
170/// fn main() -> wasmtime::Result<()> {
171/// #   if true { return Ok(()) }
172///     let engine = Engine::default();
173///     let component = Component::from_file(&engine, "./your-component.wasm")?;
174///
175///     let mut linker = Linker::new(&engine);
176///     MyWorld::add_to_linker::<_, HasSelf<_>>(&mut linker, |state| state)?;
177///
178///     let mut store = Store::new(
179///         &engine,
180///         MyState { /* ... */ },
181///     );
182///     let bindings = MyWorld::instantiate(&mut store, &component, &linker)?;
183///
184///     // ... NB: this world has no exports just yet so not much can be done
185///     // with `bindings`.
186///
187///     Ok(())
188/// }
189/// ```
190pub mod _1_world_imports;
191
192/// An example of generated bindings for top-level exported functions for a
193/// world.
194///
195/// Some notable generated items here are:
196///
197/// * [`my::project::host::Host`](_2_world_exports::my::project::host::Host) -
198///   the generated trait for the `interface host` import.
199/// * [`exports::demo::Guest`](_2_world_exports::exports::demo::Guest) -
200///   the generated structured used to invoke exports on the returned instance.
201/// * [`HelloWorld`](_2_world_exports::HelloWorld) -
202///   the overall generated structure representing our `world`.
203///
204/// ```rust
205/// use wasmtime::component::*;
206/// use wasmtime::{Engine, Store};
207///
208#[doc = include_str!("./_2_world_exports.rs")]
209///
210/// struct MyState {
211///     // ...
212/// }
213///
214/// # mod rand { pub fn thread_rng() -> G { G } pub struct G; impl G { pub fn r#gen(&self) -> u32 { 0 } } }
215/// // Note that the trait here is per-interface and within a submodule now.
216/// impl my::project::host::Host for MyState {
217///     fn gen_random_integer(&mut self) -> u32 {
218///         rand::thread_rng().r#gen()
219///     }
220///
221///     fn sha256(&mut self, bytes: Vec<u8>) -> String {
222///         // ...
223/// #       panic!()
224///     }
225/// }
226///
227/// fn main() -> wasmtime::Result<()> {
228/// #   if true { return Ok(()) }
229///     let engine = Engine::default();
230///     let component = Component::from_file(&engine, "./your-component.wasm")?;
231///
232///     let mut linker = Linker::new(&engine);
233///     HelloWorld::add_to_linker::<_, HasSelf<_>>(&mut linker, |state| state)?;
234///
235///     let mut store = Store::new(
236///         &engine,
237///         MyState { /* ... */ },
238///     );
239///     let bindings = HelloWorld::instantiate(&mut store, &component, &linker)?;
240///
241///     // Note that the `demo` method returns a `&exports::Demo::Guest`
242///     // through which we can run the methods on that interface.
243///     bindings.demo().call_run(&mut store)?;
244///     Ok(())
245/// }
246/// ```
247pub mod _2_world_exports;
248
249/// Example of generating bindings for imported interfaces in a world.
250///
251/// Notable parts of this example are:
252///
253/// * Imported interfaces use the Rust module system to encapsulate themselves.
254///   The interface imported here is `example:interface-imports/logging` so the
255///   generated trait and types are located in
256///   [`example::interface_imports::logging`][module].
257/// * Types in the `logging` interface are generated in the `logging` module,
258///   for example [`Level`].
259/// * Generated types have implementations of [`ComponentType`], [`Lift`], and
260///   [`Lower`] derived.
261/// * The generated trait that host's must implement is always called [`Host`]
262///   and is located in the generated module.
263///
264/// [module]: _3_interface_imports::example::interface_imports::logging
265/// [`Level`]: _3_interface_imports::example::interface_imports::logging::Level
266/// [`Host`]: _3_interface_imports::example::interface_imports::logging::Host
267/// [`ComponentType`]: crate::component::ComponentType
268/// [`Lift`]: crate::component::Lift
269/// [`Lower`]: crate::component::Lower
270///
271/// ```rust
272/// use wasmtime::component::bindgen;
273/// use example::interface_imports::logging::Level;
274///
275#[doc = include_str!("./_3_interface_imports.rs")]
276///
277/// struct MyState {
278///     // ...
279/// }
280///
281/// impl example::interface_imports::logging::Host for MyState {
282///     fn log(&mut self, level: Level, msg: String) {
283///         // ...
284///     }
285/// }
286/// ```
287pub mod _3_interface_imports;
288
289/// Example of generating bindings for imported resources in a world.
290///
291/// Notable parts of this example are:
292///
293/// * Imported resources from the host are represented as traits, in this case
294///   [`HostLogger`].
295/// * The per-interface [`Host`] trait still exists but has a supertrait of
296///   [`HostLogger`].
297/// * Resources are represented as [`Resource<T>`] and it's recommended to
298///   specify a `with` key to indicate what host type you'd like to use for
299///   each resource.
300/// * A [`ResourceTable`] can be used to manage resources when working with
301///   guests.
302///
303/// [`Host`]: _4_imported_resources::example::imported_resources::logging::Host
304/// [`HostLogger`]: _4_imported_resources::example::imported_resources::logging::HostLogger
305/// [`Resource<T>`]: crate::component::Resource
306/// [`ResourceTable`]: crate::component::ResourceTable
307///
308/// ```rust
309/// use wasmtime::Result;
310/// use wasmtime::component::{bindgen, ResourceTable, Resource};
311/// use example::imported_resources::logging::{Level, Host, HostLogger};
312///
313#[doc = include_str!("./_4_imported_resources.rs")]
314///
315/// #[derive(Default)]
316/// struct MyState {
317///     // Manages the mapping of `MyLogger` structures to `Resource<MyLogger>`.
318///     table: ResourceTable,
319/// }
320///
321/// // There are no free-functions on `interface logging`, so this is an empty
322/// // impl.
323/// impl Host for MyState {}
324///
325/// // This separate `HostLogger` trait serves to act as a namespace for just
326/// // the `logger`-related resource methods.
327/// impl HostLogger for MyState {
328///     // A `constructor` in WIT maps to a `new` function in Rust.
329///     fn new(&mut self, max_level: Level) -> Result<Resource<MyLogger>> {
330///         let id = self.table.push(MyLogger { max_level })?;
331///         Ok(id)
332///     }
333///
334///     fn get_max_level(&mut self, logger: Resource<MyLogger>) -> Result<Level> {
335///         debug_assert!(!logger.owned());
336///         let logger = self.table.get(&logger)?;
337///         Ok(logger.max_level)
338///     }
339///
340///     fn set_max_level(&mut self, logger: Resource<MyLogger>, level: Level) -> Result<()> {
341///         debug_assert!(!logger.owned());
342///         let logger = self.table.get_mut(&logger)?;
343///         logger.max_level = level;
344///         Ok(())
345///     }
346///
347///     fn log(&mut self, logger: Resource<MyLogger>, level: Level, msg: String) -> Result<()> {
348///         debug_assert!(!logger.owned());
349///         let logger = self.table.get_mut(&logger)?;
350///         if (level as u32) <= (logger.max_level as u32) {
351///             println!("{msg}");
352///         }
353///         Ok(())
354///     }
355///
356///     fn drop(&mut self, logger: Resource<MyLogger>) -> Result<()> {
357///         debug_assert!(logger.owned());
358///         let _logger: MyLogger = self.table.delete(logger)?;
359///         // ... custom destruction logic here if necessary, otherwise
360///         // a `Drop for MyLogger` would also work.
361///         Ok(())
362///     }
363/// }
364///
365/// # fn main() {}
366/// ```
367pub mod _4_imported_resources;
368
369/// Example of all kinds of structures of exports from a world.
370///
371/// * Top-level functions in a `world` are exported directly on the generated
372///   structure such as [`call_run`].
373/// * All other exports are otherwise scoped with generated traits/types
374///   in a top level [`exports`] module.
375/// * Exported named interfaces are located at the root of the [`exports`]
376///   module, such as [`exports::environment`].
377/// * Interfaces are all bound with a structure called `Guest` which has typed
378///   functions for each export that can be called. For example
379///   [`exports::environment::Guest`][guest1] and
380///   [`exports::example::world_exports::units::Guest`][guest2].
381/// * Interfaces exported by their id are modeled with multiple namespacing
382///   modules, such as [`exports::example::world_exports::units`][units].
383///
384/// [`call_run`]: _5_all_world_export_kinds::WithExports::call_run
385/// [`exports`]: _5_all_world_export_kinds::exports
386/// [`exports::environment`]: _5_all_world_export_kinds::exports::environment
387/// [guest1]: _5_all_world_export_kinds::exports::environment::Guest
388/// [guest2]: _5_all_world_export_kinds::exports::example::world_exports::units::Guest
389/// [units]: _5_all_world_export_kinds::exports::example::world_exports::units
390///
391/// ```rust
392/// use wasmtime::{Result, Engine, Store};
393/// use wasmtime::component::{bindgen, Component, Linker, HasSelf};
394///
395#[doc = include_str!("./_5_all_world_export_kinds.rs")]
396///
397/// struct MyState;
398///
399/// impl WithExportsImports for MyState {
400///     fn log(&mut self, msg: String) {
401///         println!("{msg}");
402///     }
403/// }
404///
405/// fn main() -> Result<()> {
406/// #   if true { return Ok(()) }
407///     let engine = Engine::default();
408///     let component = Component::from_file(&engine, "./your-component.wasm")?;
409///
410///     let mut linker = Linker::new(&engine);
411///     WithExports::add_to_linker::<_, HasSelf<_>>(&mut linker, |state| state)?;
412///
413///     let mut store = Store::new(&engine, MyState);
414///     let bindings = WithExports::instantiate(&mut store, &component, &linker)?;
415///
416///     // top-level functions are exported directly on `WithExports` and are
417///     // all prefixed with `call_*`.
418///     bindings.call_run(&mut store)?;
419///
420///     // exported named interfaces are named directly after their export name
421///     // and the `&Guest` return value has `call_*` functions on it.
422///     bindings.environment().call_set(&mut store, "key", "value")?;
423///     let value = bindings.environment().call_get(&mut store, "key")?;
424///     assert_eq!(value, "value");
425///
426///     // exported interfaces by id are similar to export-by-name except that
427///     // the exported name is modeled after the full id, not just the name.
428///     let units = bindings.example_world_exports_units();
429///     let bytes = 1 << 30 + 1 << 20;
430///     let s = units.call_bytes_to_string(&mut store, bytes)?;
431///     println!("{bytes} = {s}");
432///
433///     let (seconds, ns) = (1 << 20, 12345);
434///     let s = units.call_duration_to_string(&mut store, seconds, ns)?;
435///     println!("{seconds}s + {ns}ns = {s}");
436///     Ok(())
437/// }
438/// ```
439pub mod _5_all_world_export_kinds;
440
441/// Example of a world which exports a resource.
442///
443/// * Guest resources are modeled as [`ResourceAny`]. Note that this type is not
444///   specialized per-resource at this time so care must be taken to not mix
445///   them up.
446/// * Resource-related methods are a projection from a [`Guest`] structure, for
447///   example to [`GuestLogger`] here.
448/// * Resource-related methods all take a [`ResourceAny`] as an argument or
449///   a return value.
450/// * The [`ResourceAny`] must be explicitly dropped.
451///
452/// [`ResourceAny`]: crate::component::ResourceAny
453/// [`Guest`]: _6_exported_resources::exports::example::exported_resources::logging::Guest
454/// [`GuestLogger`]: _6_exported_resources::exports::example::exported_resources::logging::GuestLogger
455///
456/// ```rust
457/// use wasmtime::{Result, Engine, Store};
458/// use wasmtime::component::{bindgen, Component, Linker};
459/// use self::exports::example::exported_resources::logging::Level;
460///
461#[doc = include_str!("./_6_exported_resources.rs")]
462///
463/// struct MyState;
464///
465/// fn main() -> Result<()> {
466/// #   if true { return Ok(()) }
467///     let engine = Engine::default();
468///     let component = Component::from_file(&engine, "./your-component.wasm")?;
469///
470///     let linker = Linker::new(&engine);
471///     // ... this small example has no imports so nothing is added here, but
472///     // if you had imports this is where they'd go.
473///
474///     let mut store = Store::new(&engine, MyState);
475///     let bindings = ExportSomeResources::instantiate(&mut store, &component, &linker)?;
476///     let guest = bindings.example_exported_resources_logging();
477///     let logger = guest.logger();
478///
479///     // Resource methods are all attached to `logger` and take the
480///     // `ResourceAny` parameter explicitly.
481///     let my_logger = logger.call_constructor(&mut store, Level::Warn)?;
482///     assert_eq!(logger.call_get_max_level(&mut store, my_logger)?, Level::Warn);
483///     logger.call_set_max_level(&mut store, my_logger, Level::Info)?;
484///
485///     logger.call_log(&mut store, my_logger, Level::Debug, "hello!")?;
486///
487///     // The `ResourceAny` type has no destructor but when the host is done
488///     // with it it needs to invoke the guest-level destructor.
489///     my_logger.resource_drop(&mut store)?;
490///
491///     Ok(())
492/// }
493/// ```
494pub mod _6_exported_resources;
495
496/// Example of generating **async** bindings for imported resources in a world.
497///
498/// Notable differences from [`_4_imported_resources`] are:
499/// * async functions are used
500/// * enabled async in bindgen! macro
501///
502/// See [wasi_async_example](https://github.com/bytecodealliance/wasmtime/blob/main/examples/wasip1-async/main.rs) for async function calls on a host.
503///
504/// ```rust
505/// use wasmtime::Result;
506/// use wasmtime::component::{bindgen, ResourceTable, Resource};
507/// use example::imported_resources::logging::{Level, Host, HostLogger};
508///
509#[doc = include_str!("./_7_async.rs")]
510///
511/// #[derive(Default)]
512/// struct MyState {
513///     // Manages the mapping of `MyLogger` structures to `Resource<MyLogger>`.
514///     table: ResourceTable,
515/// }
516///
517/// // There are no free-functions on `interface logging`, so this is an empty
518/// // impl.
519/// impl Host for MyState {}
520///
521/// // This separate `HostLogger` trait serves to act as a namespace for just
522/// // the `logger`-related resource methods.
523/// impl HostLogger for MyState {
524///     // A `constructor` in WIT maps to a `new` function in Rust.
525///     async fn new(&mut self, max_level: Level) -> Result<Resource<MyLogger>> {
526///         let id = self.table.push(MyLogger { max_level })?;
527///         Ok(id)
528///     }
529///
530///     async fn get_max_level(&mut self, logger: Resource<MyLogger>) -> Result<Level> {
531///         debug_assert!(!logger.owned());
532///         let logger = self.table.get(&logger)?;
533///         Ok(logger.max_level)
534///     }
535///
536///     async fn set_max_level(&mut self, logger: Resource<MyLogger>, level: Level) -> Result<()> {
537///         debug_assert!(!logger.owned());
538///         let logger = self.table.get_mut(&logger)?;
539///         logger.max_level = level;
540///         Ok(())
541///     }
542///
543///     async fn log(&mut self, logger: Resource<MyLogger>, level: Level, msg: String) -> Result<()> {
544///         debug_assert!(!logger.owned());
545///         let logger = self.table.get_mut(&logger)?;
546///         if (level as u32) <= (logger.max_level as u32) {
547///             println!("{msg}");
548///         }
549///         Ok(())
550///     }
551///
552///     async fn drop(&mut self, logger: Resource<MyLogger>) -> Result<()> {
553///         debug_assert!(logger.owned());
554///         let _logger: MyLogger = self.table.delete(logger)?;
555///         // ... custom destruction logic here if necessary, otherwise
556///         // a `Drop for MyLogger` would also work.
557///         Ok(())
558///     }
559/// }
560///
561/// # fn main() {}
562/// ```
563pub mod _7_async;