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