1 use anyhow::Context; 2 use std::{fs, path::Path}; 3 4 use wasmtime::{ 5 component::{bindgen, Component, Linker}, 6 Config, Engine, Result, Store, 7 }; 8 9 // Generate bindings of the guest and host components. 10 bindgen!("convert" in "./examples/component/convert.wit"); 11 12 struct HostComponent; 13 14 // Implementation of the host interface defined in the wit file. 15 impl host::Host for HostComponent { 16 fn multiply(&mut self, a: f32, b: f32) -> f32 { 17 a * b 18 } 19 } 20 21 struct MyState { 22 host: HostComponent, 23 } 24 25 /// This function is only needed until rust can natively output a component. 26 /// 27 /// Generally embeddings should not be expected to do this programmatically, but instead 28 /// language specific tooling should be used, for example in Rust `cargo component` 29 /// is a good way of doing that: https://github.com/bytecodealliance/cargo-component 30 /// 31 /// In this example we convert the code here to simplify the testing process and build system. 32 fn convert_to_component(path: impl AsRef<Path>) -> Result<Vec<u8>> { 33 let bytes = &fs::read(&path).context("failed to read input file")?; 34 wit_component::ComponentEncoder::default() 35 .module(&bytes)? 36 .encode() 37 } 38 39 fn main() -> Result<()> { 40 // Create an engine with the component model enabled (disabled by default). 41 let engine = Engine::new(Config::new().wasm_component_model(true))?; 42 43 // NOTE: The wasm32-unknown-unknown target is used here for simplicity, real world use cases 44 // should probably use the wasm32-wasip1 target, and enable wasi preview2 within the component 45 // model. 46 let component = convert_to_component("target/wasm32-unknown-unknown/debug/guest.wasm")?; 47 48 // Create our component and call our generated host function. 49 let component = Component::from_binary(&engine, &component)?; 50 let mut store = Store::new( 51 &engine, 52 MyState { 53 host: HostComponent {}, 54 }, 55 ); 56 let mut linker = Linker::new(&engine); 57 host::add_to_linker(&mut linker, |state: &mut MyState| &mut state.host)?; 58 let convert = Convert::instantiate(&mut store, &component, &linker)?; 59 let result = convert.call_convert_celsius_to_fahrenheit(&mut store, 23.4)?; 60 println!("Converted to: {result:?}"); 61 Ok(()) 62 } 63