use anyhow::{Context, Result, anyhow};
use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex};
use wasmtime::{Config, Engine, Module, OptLevel};
use wasmtime_wasi::{WasiCtx, WasiCtxBuilder};
pub struct WasmCompiler {
engine: Arc<Engine>,
config: Config,
}
impl WasmCompiler {
pub fn new() -> Result<Self> {
let mut config = Config::default();
config.cranelift_opt_level(OptLevel::SpeedAndSize);
config.parallel_compilation(true);
config.wasm_reference_types(true);
config.wasm_simd(true);
config.wasm_bulk_memory(true);
config.wasm_multi_value(true);
let engine: _ = Engine::new(&config)
.context("Failed to create Wasmtime engine")?;
Ok(WasmCompiler {
engine: Arc::new(Mutex::new(engine)))
config,
})
}
pub fn engine(&self) -> &Arc<Engine> {
&self.engine
}
pub fn compile_js_to_wasm(&self, js_code: &str, wit_path: Option<&str>) -> Result<Vec<u8> {
let wasm_bytes: _ = self.generate_demo_wasm(js_code)?;
Ok(wasm_bytes)
}
fn generate_demo_wasm(&self, js_code: &str) -> Result<Vec<u8> {
let mut module = Module::new();
let mut types = TypeSection::new();
types.function([ValType::I32, ValType::I32], [ValType::I32]);
types.function([ValType::I32], [ValType::I32]);
let types_id: _ = module.section(&types);
let mut functions = FunctionSection::new();
functions.function(types_id, 0);
functions.function(types_id, 1);
let functions_id: _ = module.section(&functions);
let mut exports = ExportSection::new();
exports.function("add", functions_id, 0);
exports.function("main", functions_id, 1);
let _exports_id: _ = module.section(&exports);
let mut codes = CodeSection::new();
let mut func = Function::new([]);
func.instruction(&Instruction::LocalGet(0));
func.instruction(&Instruction::LocalGet(1));
func.instruction(&Instruction::I32Add);
func.instruction(&Instruction::End);
codes.function(&func);
let mut func2 = Function::new([]);
func2.instruction(&Instruction::I32Const(42));
func2.instruction(&Instruction::End);
codes.function(&func2);
module.section(&codes);
Ok(module.finish())
}
pub fn validate_wasm(&self, wasm_bytes: &[u8]) -> Result<()> {
Module::validate(&self.engine, wasm_bytes)
.context("WASM module validation failed")
}
pub fn create_wasi_context(&self) -> Result<WasiCtx> {
let wasi: _ = WasiCtxBuilder::new()
.build();
Ok(wasi)
}
pub fn get_config_info(&self) -> String {
format!(
"WasmCompiler Config:\n\
- Optimization: SpeedAndSize\n\
- Parallel Compilation: Enabled\n\
- WASM Features: Reference Types, SIMD, Bulk Memory, Multi-Value\n\
- Profiler: Perf"
)
}
}
impl Default for WasmCompiler {
fn default() -> Self {
Self::new().expect("Failed to create WasmCompiler")
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_compiler_creation() {
let compiler: _ = WasmCompiler::new();
assert!(compiler.is_ok());
}
#[test]
fn test_compiler_engine() {
let compiler: _ = WasmCompiler::new().unwrap();
assert!(compiler.engine().clone().into_parts().0.is_some());
}
#[test]
fn test_demo_wasm_generation() {
let compiler: _ = WasmCompiler::new().unwrap();
let js_code: _ = "export function add(a, b) { return a + b; }";
let wasm_bytes: _ = compiler.generate_demo_wasm(js_code);
assert!(wasm_bytes.is_ok());
let wasm_bytes: _ = wasm_bytes.unwrap();
assert!(!wasm_bytes.is_empty());
}
#[test]
fn test_wasm_validation() {
let compiler: _ = WasmCompiler::new().unwrap();
let js_code: _ = "export function test() { return 42; }";
let wasm_bytes: _ = compiler.generate_demo_wasm(js_code).unwrap();
let result: _ = compiler.validate_wasm(&wasm_bytes);
assert!(result.is_ok());
}
#[test]
fn test_config_info() {
let compiler: _ = WasmCompiler::new().unwrap();
let config_info: _ = compiler.get_config_info();
assert!(config_info.contains("WasmCompiler"));
assert!(config_info.contains("SpeedAndSize"));
assert!(config_info.contains("Parallel Compilation"));
}
#[test]
fn test_wasi_context_creation() {
let compiler: _ = WasmCompiler::new().unwrap();
let wasi: _ = compiler.create_wasi_context();
assert!(wasi.is_ok());
}
}