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)] 57 macro_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))] 65 macro_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 /// ``` 131 pub 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 /// ``` 184 pub 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 /// ``` 241 pub 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 /// ``` 281 pub 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 /// ``` 361 pub 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 /// ``` 433 pub 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 /// ``` 488 pub 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 /// ``` 557 pub mod _7_async; 558