use anyhow::Context;
mod abi;
#[cfg(test)]
mod fuzz_common;
mod indices;
mod mem_layout;
mod resolve;
mod tier1;
mod tier2;
pub mod typed;
use tier1::build_adapter;
use tier2::build_tier2_adapter;
const TIER1_WORLD_WIT: &str = include_str!("../../wit/tier1/world.wit");
const TIER2_WORLD_WIT: &str = include_str!("../../wit/tier2/world.wit");
const COMMON_WORLD_WIT: &str = include_str!("../../wit/common/world.wit");
pub fn generate_tier1_adapter(
middleware_name: &str,
target_interface: &str,
middleware_interfaces: &[String],
splits_output_path: &str,
split_path: &str,
) -> anyhow::Result<String> {
let has_before = middleware_interfaces.iter().any(|i| i.contains("/before"));
let has_after = middleware_interfaces.iter().any(|i| i.contains("/after"));
let has_blocking = middleware_interfaces
.iter()
.any(|i| i.contains("/blocking"));
write_adapter(
middleware_name,
target_interface,
splits_output_path,
split_path,
"splicer_adapter",
|split_bytes| {
build_adapter(
target_interface,
has_before,
has_after,
has_blocking,
split_bytes,
COMMON_WORLD_WIT,
TIER1_WORLD_WIT,
)
},
)
}
pub fn generate_tier2_adapter(
middleware_name: &str,
target_interface: &str,
middleware_interfaces: &[String],
splits_output_path: &str,
split_path: &str,
) -> anyhow::Result<String> {
let has_before = middleware_interfaces.iter().any(|i| i.contains("/before"));
let has_after = middleware_interfaces.iter().any(|i| i.contains("/after"));
write_adapter(
middleware_name,
target_interface,
splits_output_path,
split_path,
"splicer_adapter_tier2",
|split_bytes| {
build_tier2_adapter(
target_interface,
has_before,
has_after,
split_bytes,
COMMON_WORLD_WIT,
TIER2_WORLD_WIT,
)
},
)
}
fn write_adapter(
middleware_name: &str,
target_interface: &str,
splits_output_path: &str,
split_path: &str,
out_name_prefix: &str,
build_bytes: impl FnOnce(&[u8]) -> anyhow::Result<Vec<u8>>,
) -> anyhow::Result<String> {
let split_bytes = std::fs::read(split_path)
.with_context(|| format!("Failed to read split at '{split_path}'"))?;
let bytes = build_bytes(&split_bytes)?;
let out_path = format!(
"{splits_output_path}/{out_name_prefix}_{}_{}.wasm",
sanitize_name(middleware_name),
sanitize_name(target_interface)
);
std::fs::write(&out_path, &bytes)
.with_context(|| format!("Failed to write adapter component to '{}'", out_path))?;
Ok(out_path)
}
fn sanitize_name(s: &str) -> String {
s.chars()
.map(|c| if c.is_alphanumeric() { c } else { '_' })
.collect()
}