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