use anyhow::{Context as AnyhowContext, Result};
use bytes::Bytes;
use wasmtime::{component::Component, error::Context, Config, Engine};
use wit_component::ComponentEncoder;
static WASI_ADAPTER: &[u8] = include_bytes!("../res/wasi_snapshot_preview1.reactor.wasm");
#[derive(Clone)]
pub struct Image {
engine: Engine,
component: Component,
}
fn apply_config_defaults(config: &mut Config) {
config.wasm_component_model(true);
}
impl Image {
pub fn new(wasm_binary: Bytes) -> Result<Self> {
Self::new_with_config(wasm_binary, Config::new())
}
pub fn new_with_config(wasm_binary: Bytes, mut config: Config) -> Result<Self> {
apply_config_defaults(&mut config);
let engine = Engine::new(&config).context("Failed to create WASM engine")?;
let component_binary = ComponentEncoder::default()
.module(wasm_binary.as_ref())
.context("Failed to parse WASM module")?
.validate(true)
.adapter("wasi_snapshot_preview1", WASI_ADAPTER)
.context("Failed to add WASI adapter")?
.encode()
.context("Failed to encode WASM component")?;
let component = Component::from_binary(&engine, &component_binary)
.context("Failed to compile WASM component")?;
Ok(Self { engine, component })
}
pub fn from_component(component_binary: Bytes) -> Result<Self> {
Self::from_component_with_config(component_binary, Config::new())
}
pub fn from_component_with_config(component_binary: Bytes, mut config: Config) -> Result<Self> {
apply_config_defaults(&mut config);
let engine = Engine::new(&config).context("Failed to create WASM engine")?;
let component = Component::from_binary(&engine, component_binary.as_ref())
.context("Failed to compile WASM component")?;
Ok(Self { engine, component })
}
pub(crate) fn engine(&self) -> &Engine {
&self.engine
}
pub(crate) fn component(&self) -> &Component {
&self.component
}
}
impl std::fmt::Debug for Image {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Image").finish()
}
}