use std::sync::Arc; use parking_lot::RwLock; use paste::paste; use crate::dynamic_data::{DynamicLibrary, TurnChoice}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData; use crate::static_data::EffectParameter; use crate::StringKey; use wasmer::TypedFunction; /// A macro to generate the script function cache a bit easier. macro_rules! script_function_cache { ( $( $name:ident($($par_type:ty),*$(,)?) )* ) => { #[derive(Default)] #[allow(unused_parens)] pub struct ScriptFunctionCache { $( $name: RwLock>>, )* } impl ScriptFunctionCache { $( paste! { #[cold] #[allow(unused_parens)] fn [](&self, env: &Arc) { let exported = env.exported_functions(); let f = exported.get::(&stringify!([< script_ $name >]).into()); if let Some(f) = f { let func: TypedFunction<(u32 $(,$par_type)*), ()> = f.typed(&env.store_ref()).unwrap(); let _ = self.$name.write().insert(func); } } #[allow(unused_parens)] pub(crate) fn [<$name>]( &self, env: &Arc, ) -> Option> { { let read_lock = self.$name.read(); if let Some(f) = read_lock.as_ref() { return Some(f.clone()); } } self.[](env); self.$name.read().as_ref().cloned() } } )* } } } script_function_cache! { stack() on_remove() on_initialize(ExternRef, VecExternRef) on_before_turn(ExternRef) change_speed(ExternRef, u32) change_priority(ExternRef, u32) }