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