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;