component_init_wasmtime/
lib.rs1use anyhow::{Context, Result, anyhow};
2use component_init_transform::Invoker;
3use wasmtime::{
4 Config, Engine, Store,
5 component::{Component, ComponentNamedList, Instance, Lift, Linker},
6};
7
8pub async fn initialize(component: &[u8]) -> Result<Vec<u8>> {
9 component_init_transform::initialize(component, |instrumented| {
10 Box::pin(async move {
11 let i = invoker(instrumented)
12 .await
13 .context("running instrumented component")?;
14 let i: Box<dyn Invoker> = Box::new(i);
15 Ok(i)
16 })
17 })
18 .await
19}
20
21async fn invoker(component: Vec<u8>) -> Result<Impl> {
22 let mut config = Config::new();
23 config.async_support(true);
24 let engine = Engine::new(&config).context("creating engine")?;
25 let component =
26 Component::new(&engine, &component).context("compiling instrumented component")?;
27 let mut linker = Linker::new(&engine);
28 linker
29 .define_unknown_imports_as_traps(&component)
30 .context("link unknown imports as traps")?;
31 let mut store = Store::new(&engine, Ctx);
32 let instance = linker
33 .instantiate_async(&mut store, &component)
34 .await
35 .context("instantiate")?;
36 let mut this = Impl { instance, store };
37 this.call::<()>("component-init")
38 .await
39 .context("running the component-init export func")?;
40 Ok(this)
41}
42
43pub struct Ctx;
44
45struct Impl {
46 instance: Instance,
47 store: Store<Ctx>,
48}
49
50impl Impl {
51 async fn call<T: ComponentNamedList + Lift + Send + Sync>(&mut self, name: &str) -> Result<T> {
52 let export = self
53 .instance
54 .get_export_index(&mut self.store, None, name)
55 .ok_or_else(|| anyhow!("{name} is not exported"))?;
56 let func = self
57 .instance
58 .get_func(&mut self.store, export)
59 .ok_or_else(|| anyhow!("{name} export is not a func"))?;
60 let func = func
61 .typed::<(), T>(&mut self.store)
62 .with_context(|| format!("type of {name} func"))?;
63 let r = func
64 .call_async(&mut self.store, ())
65 .await
66 .with_context(|| format!("executing {name}"))?;
67 func.post_return_async(&mut self.store)
68 .await
69 .with_context(|| format!("post-return {name}"))?;
70 Ok(r)
71 }
72}
73
74#[async_trait::async_trait]
75impl Invoker for Impl {
76 async fn call_s32(&mut self, name: &str) -> Result<i32> {
77 Ok(self.call::<(i32,)>(name).await?.0)
78 }
79 async fn call_s64(&mut self, name: &str) -> Result<i64> {
80 Ok(self.call::<(i64,)>(name).await?.0)
81 }
82 async fn call_f32(&mut self, name: &str) -> Result<f32> {
83 Ok(self.call::<(f32,)>(name).await?.0)
84 }
85 async fn call_f64(&mut self, name: &str) -> Result<f64> {
86 Ok(self.call::<(f64,)>(name).await?.0)
87 }
88 async fn call_list_u8(&mut self, name: &str) -> Result<Vec<u8>> {
89 Ok(self.call::<(Vec<u8>,)>(name).await?.0)
90 }
91}