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