From 73ffbee638c03da132aea0e5d600ca5e8144fd8e Mon Sep 17 00:00:00 2001 From: Mica White Date: Fri, 3 Jul 2026 15:33:08 -0400 Subject: Support WASM, kinda --- src/script.rs | 138 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 84 insertions(+), 54 deletions(-) (limited to 'src/script.rs') diff --git a/src/script.rs b/src/script.rs index eeb943f..e1634a6 100644 --- a/src/script.rs +++ b/src/script.rs @@ -1,7 +1,6 @@ use std::path::Path; use rustc_hash::FxHashMap; -use wasmer::{Imports, Instance, Module, Store}; use crate::{buffer::Buffer, file::FileManager, input::InputManager}; @@ -11,12 +10,17 @@ pub struct ScriptManager<'a> { script_states: FxHashMap>, } +pub struct WasmRunner { + pub engine: wasmi::Engine, + pub linker: wasmi::Linker<&'static ScriptContext<'static>>, +} + pub struct ScriptContext<'a> { pub buffer: &'a mut Buffer, pub input: &'a InputManager, } -type StaticScriptFunction = Option)>; +type StaticScriptFunction = Option, &mut Box<[u8]>)>; pub enum ScriptDeclaration { Static { @@ -29,17 +33,6 @@ pub enum ScriptDeclaration { }, } -pub struct WasmScript { - pub module: Module, - pub instance: Instance, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum Profile { - Debug, - Release, -} - impl<'a> ScriptContext<'a> { pub fn exit(&mut self) -> ! { let _ = self.buffer.finish(); @@ -51,6 +44,42 @@ fn get_script_state(states: &mut FxHashMap>, script_id: usize) states.entry(script_id).or_insert(Box::from([])) } +impl Default for WasmRunner { + fn default() -> Self { + Self::new() + } +} + +impl WasmRunner { + pub fn new() -> Self { + let engine = wasmi::Engine::default(); + let linker = wasmi::Linker::new(&engine); + Self { engine, linker } + } + + pub fn compile(&self, data: &[u8]) -> Result { + wasmi::Module::new(&self.engine, data) + } + + pub fn run_function( + &self, + module: &wasmi::Module, + context: &mut ScriptContext<'_>, + function_name: &str, + ) -> Result<(), wasmi::Error> { + // safety: the store won't be kept around after this function ends. Only the + // lifetimes are being transmuted + let mut store = wasmi::Store::new(&self.engine, unsafe { + std::mem::transmute::<&ScriptContext<'_>, &ScriptContext<'_>>(context) + }); + let instance = self.linker.instantiate_and_start(&mut store, module)?; + let function = instance.get_func(&store, function_name).ok_or_else(|| { + wasmi::Error::new(format!("No function named {function_name} was exported")) + })?; + function.call(&mut store, &[], &mut []) + } +} + impl<'a> ScriptManager<'a> { pub fn new(scripts: &'a [ScriptDeclaration]) -> Self { Self { @@ -64,6 +93,7 @@ impl<'a> ScriptManager<'a> { &mut self, script_id: usize, context: &mut ScriptContext<'_>, + wasm_runner: &WasmRunner, files: &mut FileManager, ) { let Some(script_declaration) = self.scripts.get(script_id) else { @@ -79,19 +109,23 @@ impl<'a> ScriptManager<'a> { }); } ScriptDeclaration::Wasm { path } => { - todo!("wasm scripts") - // let module = files.load_file(path.clone()).unwrap().unwrap_wasm_module(); - // let mut store = wasmi::Store::new(&files.wasm_compiler, context); - // let instance = self - // .linker - // .instantiate_and_start(&mut store, &module) - // .unwrap(); + let module = files + .load_file(path.clone(), &wasm_runner.engine) + .unwrap() + .unwrap_wasm_module(); + wasm_runner.run_function(module, context, "start"); } } self.active_scripts.push(script_id); } - pub fn deactivate_script(&mut self, script_id: usize, context: &mut ScriptContext<'_>) { + pub fn deactivate_script( + &mut self, + script_id: usize, + context: &mut ScriptContext<'_>, + wasm_runner: &WasmRunner, + files: &mut FileManager, + ) { self.active_scripts.retain(|element| { if *element != script_id { let Some(script) = self.scripts.get(script_id) else { @@ -106,7 +140,13 @@ impl<'a> ScriptManager<'a> { ); }); } - ScriptDeclaration::Wasm { .. } => todo!("wasm scripts"), + ScriptDeclaration::Wasm { path } => { + let module = files + .load_file(path.clone(), &wasm_runner.engine) + .unwrap() + .unwrap_wasm_module(); + wasm_runner.run_function(module, context, "end"); + } }; true @@ -116,12 +156,17 @@ impl<'a> ScriptManager<'a> { }); } - pub fn run_scripts(&mut self, context: &mut ScriptContext<'_>) { + pub fn run_scripts( + &mut self, + context: &mut ScriptContext<'_>, + wasm_runner: &WasmRunner, + files: &mut FileManager, + ) { for script_id in &self.active_scripts { let Some(script) = self.scripts.get(*script_id) else { unreachable!("The active script does not exist"); }; - match *script { + match script { ScriptDeclaration::Static { update, .. } => { if let Some(s) = update { s( @@ -130,40 +175,25 @@ impl<'a> ScriptManager<'a> { ) } } - ScriptDeclaration::Wasm { .. } => todo!("wasm scripts"), - } - } - } - - pub fn reset_script(&mut self, script_id: usize, context: &mut ScriptContext<'_>) { - let script = &self.scripts[script_id]; - match script { - ScriptDeclaration::Static { start, end, .. } => { - if let Some(s) = start { - s( - context, - get_script_state(&mut self.script_states, script_id), - ) - } - if let Some(s) = end { - s( - context, - get_script_state(&mut self.script_states, script_id), - ) + ScriptDeclaration::Wasm { path } => { + let module = files + .load_file(path.clone(), &wasm_runner.engine) + .unwrap() + .unwrap_wasm_module(); + wasm_runner.run_function(module, context, "update"); } } - ScriptDeclaration::Wasm { .. } => todo!("wasm scripts"), } } -} -impl WasmScript { - fn call_function(&self, name: &str, profile: Profile, store: &mut Store, imports: &Imports) { - let instance = match profile { - Profile::Debug => &Instance::new(store, &self.module, imports).unwrap(), - Profile::Release => &self.instance, - }; - let function = instance.exports.get_function(name).unwrap(); - function.call(store, &[]).unwrap(); + pub fn reset_script( + &mut self, + script_id: usize, + context: &mut ScriptContext<'_>, + wasm_runner: &WasmRunner, + files: &mut FileManager, + ) { + self.activate_script(script_id, context, wasm_runner, files); + self.deactivate_script(script_id, context, wasm_runner, files); } } -- cgit v1.2.3