diff --git a/Cargo.toml b/Cargo.toml index e7a503c..002e19e 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ hashbrown = "0.13.1" indexmap = "1.8.2" parking_lot = "0.12.1" serde = { version = "1.0.137", optional = true, features = ["derive"] } -wasmer = { version = "3.1.1", optional = true, default-features = false, features = ["sys", "wat", "cranelift"] } +wasmer = { version = "3.3.0", optional = true, default-features = false, features = ["sys", "wat", "llvm"] } uuid = "1.2.2" paste = { version = "1.0.8" } arcstr = { version = "1.1.4", features = ["std"] } @@ -61,6 +61,7 @@ enum-display-derive = "0.1.1" anyhow = "1.0.69" anyhow_ext = "0.2.1" thiserror = "1.0.39" +stdext = "0.3.1" [dev-dependencies] csv = "1.1.6" diff --git a/src/dynamic_data/event_hooks.rs b/src/dynamic_data/event_hooks.rs index c9fa9a1..7f80222 100755 --- a/src/dynamic_data/event_hooks.rs +++ b/src/dynamic_data/event_hooks.rs @@ -1,6 +1,6 @@ -use parking_lot::RwLock; use std::fmt::{Debug, Formatter}; use std::sync::Arc; +use std::sync::RwLock; use crate::dynamic_data::DamageSource; use crate::dynamic_data::ExecutingMove; @@ -29,14 +29,15 @@ impl EventHook { /// listeners can exist at the same time. Note that for these functions the event will be disposed /// of after the event is finished being sent. pub fn register_listener(&self, func: EvtHookFn) { - self.evt_hook_function.write().push(func); + self.evt_hook_function.write().unwrap().push(func); } /// Run a new event. This will send the event to all externally defined event listeners. It will /// dispose of the event afterwards. pub fn trigger(&self, evt: Event) { let b = Box::new(&evt); - for f in self.evt_hook_function.read().iter() { + let read_lock = self.evt_hook_function.read().unwrap(); + for f in read_lock.iter() { f(&b); } } diff --git a/src/dynamic_data/models/battle.rs b/src/dynamic_data/models/battle.rs index a35df64..8a6c5d7 100755 --- a/src/dynamic_data/models/battle.rs +++ b/src/dynamic_data/models/battle.rs @@ -70,7 +70,7 @@ impl Battle { number_of_sides: u8, pokemon_per_side: u8, random_seed: Option, - ) -> Self { + ) -> Arc { // If no seed was passed, we use the current time as seed for the RNG, otherwise we use the // seed. let random = if let Some(seed) = random_seed { @@ -83,7 +83,7 @@ impl Battle { sides.push(BattleSide::new(i, pokemon_per_side)); } - let mut battle = Self { + let battle = Self { identifier: Default::default(), library, parties, @@ -103,12 +103,16 @@ impl Battle { script_source_data: Default::default(), }; - let ptr: *mut Battle = &mut battle; - for side in &mut battle.sides { - side.set_battle(ptr); + let battle_arc = Arc::new(battle); + + let battle_ptr = Arc::as_ptr(&battle_arc) as *mut Battle; + unsafe { + for side in &mut battle_ptr.as_mut().unwrap().sides { + side.set_battle(Arc::downgrade(&battle_arc)); + } } - battle + battle_arc } /// The library the battle uses for handling. @@ -135,10 +139,6 @@ impl Battle { pub fn sides(&self) -> &Vec { &self.sides } - /// A mutable list of all sides in the battle. - pub fn sides_mut(&mut self) -> &mut Vec { - &mut self.sides - } /// The RNG used for the battle. pub fn random(&self) -> &BattleRandom { &self.random diff --git a/src/dynamic_data/models/battle_side.rs b/src/dynamic_data/models/battle_side.rs index 8b9b8f2..8d878ba 100755 --- a/src/dynamic_data/models/battle_side.rs +++ b/src/dynamic_data/models/battle_side.rs @@ -1,6 +1,6 @@ use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; -use std::sync::Arc; +use std::sync::{Arc, Weak}; use anyhow::{anyhow, Result}; use parking_lot::lock_api::RwLockReadGuard; @@ -35,7 +35,7 @@ pub struct BattleSide { /// The number of choices that are set. choices_set: AtomicU8, /// A reference to the battle we're part of. - battle: *mut Battle, + battle: Weak, /// Whether or not this side has fled. has_fled_battle: bool, /// The volatile scripts that are attached to the side. @@ -68,7 +68,7 @@ impl BattleSide { choices, fillable_slots, choices_set: AtomicU8::new(0), - battle: std::ptr::null_mut::(), + battle: Weak::new(), has_fled_battle: false, volatile_scripts: Default::default(), script_source_data: Default::default(), @@ -76,7 +76,7 @@ impl BattleSide { } /// Set the battle this side belongs to. - pub(crate) fn set_battle(&mut self, battle: *mut Battle) { + pub(crate) fn set_battle(&mut self, battle: Weak) { self.battle = battle; } @@ -106,8 +106,10 @@ impl BattleSide { self.choices_set.load(Ordering::SeqCst) } /// A reference to the battle we're part of. - pub fn battle(&self) -> Result<&Battle> { - unsafe { self.battle.as_ref().ok_or(anyhow!("Battle was not set, but requested")) } + pub fn battle(&self) -> Result> { + self.battle + .upgrade() + .ok_or(anyhow!("Battle was not set, but requested")) } /// Whether or not this side has fled. pub fn has_fled_battle(&self) -> bool { @@ -194,7 +196,7 @@ impl BattleSide { &read_lock.get_res(index as usize)?.clone() }; if let Some(pokemon) = pokemon { - pokemon.set_battle_data(self.battle, self.index); + pokemon.set_battle_data(self.battle.clone(), self.index); pokemon.set_on_battlefield(true)?; pokemon.set_battle_index(index); @@ -227,7 +229,7 @@ impl BattleSide { /// Checks whether a Pokemon is on the field in this side. pub fn is_pokemon_on_side(&self, pokemon: Arc) -> bool { for p in self.pokemon.read().iter().flatten() { - if std::ptr::eq(p.deref().deref(), pokemon.deref()) { + if Arc::ptr_eq(p, &pokemon) { return true; } } @@ -247,7 +249,7 @@ impl BattleSide { pub fn is_slot_unfillable(&self, pokemon: Arc) -> Result { for (i, slot) in self.pokemon.read().iter().enumerate() { if let Some(p) = slot { - if std::ptr::eq(p.deref().deref(), pokemon.deref()) { + if Arc::ptr_eq(p, &pokemon) { return Ok(self.fillable_slots.get_res(i)?.load(Ordering::Relaxed)); } } @@ -290,7 +292,8 @@ impl BattleSide { // Fetch parties for the two indices. let mut party_a = None; let mut party_b = None; - for party in self.battle()?.parties() { + let battle = self.battle()?; + for party in battle.parties() { if party.is_responsible_for_index(self.index, a) { party_a = Some(party); } diff --git a/src/dynamic_data/models/executing_move.rs b/src/dynamic_data/models/executing_move.rs index 249e626..aa060d1 100755 --- a/src/dynamic_data/models/executing_move.rs +++ b/src/dynamic_data/models/executing_move.rs @@ -1,4 +1,3 @@ -use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering}; use std::sync::Arc; @@ -166,10 +165,10 @@ impl ExecutingMove { } /// Gets a hit data for a target, with a specific index. - pub fn get_hit_data(&self, for_target: &Pokemon, hit: u8) -> Result<&HitData> { + pub fn get_hit_data(&self, for_target: &Arc, hit: u8) -> Result<&HitData> { for (index, target) in self.targets.iter().enumerate() { if let Some(target) = target { - if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) { + if Arc::ptr_eq(target, for_target) { let i = index * self.number_of_hits as usize + hit as usize; return match self.hits.get(i) { Some(hit) => Ok(hit), @@ -188,7 +187,7 @@ impl ExecutingMove { /// Checks whether a Pokemon is a target for this move. pub fn is_pokemon_target(&self, pokemon: &Arc) -> bool { for target in self.targets.iter().flatten() { - if std::ptr::eq(target.deref().deref(), pokemon.deref().deref()) { + if Arc::ptr_eq(target, pokemon) { return true; } } @@ -199,7 +198,7 @@ impl ExecutingMove { pub(crate) fn get_index_of_target(&self, for_target: &Arc) -> Result { for (index, target) in self.targets.iter().enumerate() { if let Some(target) = target { - if std::ptr::eq(target.deref().deref(), for_target.deref().deref()) { + if Arc::ptr_eq(target, for_target) { let i = index * self.number_of_hits as usize; return Ok(i); } diff --git a/src/dynamic_data/models/learned_move.rs b/src/dynamic_data/models/learned_move.rs index 0c6e844..e6bdf84 100755 --- a/src/dynamic_data/models/learned_move.rs +++ b/src/dynamic_data/models/learned_move.rs @@ -1,4 +1,3 @@ -use anyhow::Result; use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::Arc; @@ -81,7 +80,7 @@ impl LearnedMove { } /// Restore the remaining PP by a certain amount. Will prevent it from going above max PP. - pub fn restore_uses(&self, mut uses: u8) -> Result<()> { + pub fn restore_uses(&self, mut uses: u8) { self.remaining_pp .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { if x + uses > self.max_pp { @@ -90,7 +89,6 @@ impl LearnedMove { Some(x + uses) }) .ok(); - Ok(()) } } @@ -113,7 +111,7 @@ mod tests { let data: Arc = Arc::new(mock); let learned_move = LearnedMove::new(data, MoveLearnMethod::Level); assert!(learned_move.try_use(15)); - learned_move.restore_uses(5).unwrap(); + learned_move.restore_uses(5); assert_eq!(20, learned_move.remaining_pp()); } } diff --git a/src/dynamic_data/models/pokemon.rs b/src/dynamic_data/models/pokemon.rs index 2a9091a..20e6cc4 100755 --- a/src/dynamic_data/models/pokemon.rs +++ b/src/dynamic_data/models/pokemon.rs @@ -1,3 +1,4 @@ +use std::fmt::{Debug, Formatter}; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering}; use std::sync::{Arc, Weak}; @@ -26,7 +27,6 @@ use crate::{script_hook, PkmnError, StringKey, ValueIdentifiable, ValueIdentifie use anyhow::{anyhow, bail, Result}; /// An individual Pokemon as we know and love them. -#[derive(Debug)] pub struct Pokemon { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, @@ -392,10 +392,10 @@ impl Pokemon { } /// Gets the battle the battle is currently in. - pub fn get_battle(&self) -> Option<&Battle> { + pub fn get_battle(&self) -> Option> { let r = self.battle_data.read(); if let Some(data) = &r.deref() { - unsafe { data.battle.as_ref() } + data.battle.upgrade() } else { None } @@ -480,13 +480,8 @@ impl Pokemon { // If we're in battle, use the battle random for predictability let r = self.battle_data.read(); if let Some(data) = r.deref() { - let mut random = match data - .battle() - .ok_or(anyhow!("Battle not set"))? - .random() - .get_rng() - .lock() - { + let battle = data.battle().ok_or(anyhow!("Battle not set"))?; + let mut random = match battle.random().get_rng().lock() { Ok(v) => v, Err(_) => return Err(PkmnError::UnableToAcquireLock.into()), }; @@ -585,7 +580,7 @@ impl Pokemon { } /// Sets the current battle the Pokemon is in. - pub fn set_battle_data(&self, battle: *mut Battle, battle_side_index: u8) { + pub fn set_battle_data(&self, battle: Weak, battle_side_index: u8) { let mut w = self.battle_data.write(); if let Some(battle_data) = w.deref_mut() { battle_data.battle = battle; @@ -770,7 +765,7 @@ impl Pokemon { #[derive(Debug)] pub struct PokemonBattleData { /// The battle data of the Pokemon - battle: *mut Battle, + battle: Weak, /// The index of the side of the Pokemon battle_side_index: AtomicU8, /// The index of the slot on the side of the Pokemon. @@ -783,12 +778,12 @@ pub struct PokemonBattleData { impl PokemonBattleData { /// The battle data of the Pokemon - pub fn battle_mut(&mut self) -> Option<&mut Battle> { - unsafe { self.battle.as_mut() } + pub fn battle_mut(&mut self) -> Option> { + self.battle.upgrade() } /// The battle data of the Pokemon - pub fn battle(&self) -> Option<&Battle> { - unsafe { self.battle.as_ref() } + pub fn battle(&self) -> Option> { + self.battle.upgrade() } /// The index of the side of the Pokemon @@ -876,6 +871,18 @@ pub enum DamageSource { Struggle = 2, } +impl Debug for Pokemon { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str("Pokemon(")?; + write!(f, "Species: {}, ", self.species().name())?; + write!(f, "Form: {}, ", self.form().name())?; + write!(f, "Level: {}, ", self.level())?; + + f.write_str(")")?; + Ok(()) + } +} + #[cfg(test)] #[allow(clippy::unwrap_used)] pub mod test { diff --git a/src/ffi/dynamic_data/models/battle.rs b/src/ffi/dynamic_data/models/battle.rs index df44137..8f03fb8 100644 --- a/src/ffi/dynamic_data/models/battle.rs +++ b/src/ffi/dynamic_data/models/battle.rs @@ -19,7 +19,7 @@ extern "C" fn battle_new( // NOTE: Split into two due to u128 not being ABI safe: https://github.com/rust-lang/rust/issues/54341 random_seed_1: u64, random_seed_2: u64, -) -> IdentifiablePointer { +) -> IdentifiablePointer> { let parties = unsafe { std::slice::from_raw_parts(parties, parties_length) .iter() @@ -34,14 +34,14 @@ extern "C" fn battle_new( }; let random_seed = if random_seed == 0 { None } else { Some(random_seed) }; - Box::new(Battle::new( + Battle::new( library.as_ref().clone(), parties, can_flee == 1, number_of_sides, pokemon_per_side, random_seed, - )) + ) .into() } diff --git a/src/ffi/dynamic_data/models/pokemon.rs b/src/ffi/dynamic_data/models/pokemon.rs index 055c407..dd3eb01 100644 --- a/src/ffi/dynamic_data/models/pokemon.rs +++ b/src/ffi/dynamic_data/models/pokemon.rs @@ -251,9 +251,9 @@ extern "C" fn pokemon_set_effort_value( /// Gets the data for the battle the Pokemon is currently in. If the Pokemon is not in a battle, this /// returns null. #[no_mangle] -extern "C" fn pokemon_get_battle(ptr: ExternPointer>) -> IdentifiablePointer { +extern "C" fn pokemon_get_battle(ptr: ExternPointer>) -> IdentifiablePointer> { if let Some(v) = ptr.as_ref().get_battle() { - (v as *const Battle).into() + v.into() } else { IdentifiablePointer::none() } diff --git a/src/lib.rs b/src/lib.rs index 2898c70..35e56e1 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ #![allow(clippy::borrowed_box)] #![allow(incomplete_features)] #![allow(ambiguous_glob_reexports)] +#![allow(hidden_glob_reexports)] #![deny(missing_docs)] #![deny(clippy::missing_docs_in_private_items)] // Linter rules to prevent panics diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/battle.rs b/src/script_implementations/wasm/export_registry/dynamic_data/battle.rs index 5905cb8..7597b10 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/battle.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/battle.rs @@ -1,10 +1,14 @@ use crate::dynamic_data::{ Battle, BattleParty, BattleRandom, BattleResult, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, PokemonParty, }; -use crate::script_implementations::wasm::export_registry::{register, WasmResult}; +use crate::script_implementations::wasm::export_registry::wasm_result::{ + get_value, get_value_arc, get_value_call_getter, try_wasm, +}; +use crate::script_implementations::wasm::export_registry::{register, wasm_ok, WasmResult}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::StringKey; +use anyhow_ext::Context; use wasmer::FunctionEnvMut; register! { @@ -12,59 +16,66 @@ register! { env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult { - Ok(battle.value_func(&env)?.pokemon_per_side()).into() + let value = get_value_call_getter!(battle.pokemon_per_side(), env); + wasm_ok(value) } fn battle_get_parties( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult> { - Ok(VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env)?.parties())).into() + let parties = get_value_call_getter!(battle.parties(), env); + wasm_ok(VecExternRef::new(env.data().data().as_ref(), parties)) } fn battle_get_choice_queue( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult> { - let queue = battle.value_func(&env)?.current_turn_queue().read(); - Ok(if let Some(queue) = queue.as_ref() { - ExternRef::func_new(&env, queue) + let value = get_value_call_getter!(battle.current_turn_queue(), env); + let queue = value.read(); + wasm_ok(if let Some(queue) = queue.as_ref() { + ExternRef::::func_new(&env, queue) } else { ExternRef::null() - }).into() + }) } fn battle_get_library( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, &battle.value_func(&env)?.library().clone())).into() + let value = get_value_call_getter!(battle.library(), env); + wasm_ok(ExternRef::::func_new(&env, &value.clone())) } fn battle_get_sides( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult> { - Ok(VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env)?.sides())).into() + let value = get_value_arc!(battle, env); + wasm_ok(VecExternRef::new(env.data().data().as_ref(), value.sides())) } fn battle_get_random( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, battle.value_func(&env)?.random())).into() + let random = get_value_call_getter!(battle.random(), env); + wasm_ok(ExternRef::::func_new(&env, random)) } fn battle_get_weather_name( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult> { - let weather = battle.value_func(&env)?.weather_name()?; - Ok(if let Some(weather) = weather { - ExternRef::func_new(&env, &weather) + let weather = get_value_call_getter!(battle.weather_name(), env); + let weather = try_wasm!(weather, env); + wasm_ok(if let Some(weather) = weather { + ExternRef::::func_new(&env, &weather) } else { ExternRef::null() - }).into() + }) } fn battle_find_party_for_pokemon( @@ -72,14 +83,14 @@ register! { battle: ExternRef, pokemon: ExternRef ) -> WasmResult> { - let battle = battle.value_func(&env)?; - let pokemon = pokemon.value_func(&env)?; + let battle = get_value!(battle, env); + let pokemon = get_value!(pokemon, env); for party in battle.parties() { if party.party().has_pokemon(pokemon) { - return Ok(ExternRef::func_new(&env, party)).into(); + return wasm_ok(ExternRef::::func_new(&env, party)); } } - Ok(ExternRef::null()).into() + wasm_ok(ExternRef::::null()) } fn battle_get_pokemon( @@ -87,65 +98,68 @@ register! { battle: ExternRef, side: u8, index: u8 ) -> WasmResult> { - let battle = battle.value_func(&env)?; + let battle = get_value!(battle, env); let pokemon = battle.get_pokemon(side, index); - Ok(if let Some(pokemon) = pokemon { - ExternRef::func_new(&env, &pokemon) + wasm_ok(if let Some(pokemon) = pokemon { + ExternRef::::func_new(&env, &pokemon) } else { ExternRef::null() - }).into() + }) } fn battle_get_can_flee( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult { - Ok(if battle.value_func(&env)?.can_flee() { 1 } else { 0 }).into() + wasm_ok(if get_value_call_getter!(battle.can_flee(), env) { 1 } else { 0 }) } fn battle_get_number_of_sides( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult { - Ok(battle.value_func(&env)?.number_of_sides()).into() + wasm_ok(get_value_call_getter!(battle.number_of_sides(), env)) } fn battle_get_has_ended( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult { - Ok(if battle.value_func(&env)?.has_ended() { 1 } else { 0 }).into() + wasm_ok(if get_value_call_getter!(battle.has_ended(), env) { 1u8 } else { 0u8 }) } fn battle_get_has_ended_conclusively( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult { - Ok(if battle.value_func(&env)?.result().is_conclusive() { 1 } else { 0 }).into() + let value = get_value_call_getter!(battle.result(), env); + wasm_ok(if value.is_conclusive() { 1 } else { 0 }) } fn battle_get_winning_side( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult { - Ok(if let BattleResult::Conclusive(result) = battle.value_func(&env)?.result() { + let value = get_value_call_getter!(battle.result(), env); + wasm_ok(if let BattleResult::Conclusive(result) = value { result } else { 0 - }).into() + }) } fn battle_get_current_turn( env: FunctionEnvMut, battle: ExternRef, ) -> WasmResult { - Ok(battle.value_func(&env)?.current_turn()).into() + wasm_ok(get_value_call_getter!(battle.current_turn(), env)) } fn battle_party_get_party( env: FunctionEnvMut, battle_party: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, battle_party.value_func(&env)?.party().as_ref())).into() + let value = get_value_call_getter!(battle_party.party(), env); + wasm_ok(ExternRef::::func_new(&env, value.as_ref())) } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/battle_random.rs b/src/script_implementations/wasm/export_registry/dynamic_data/battle_random.rs index 077dd7c..fa1894e 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/battle_random.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/battle_random.rs @@ -1,23 +1,31 @@ use crate::dynamic_data::BattleRandom; +use crate::script_implementations::wasm::export_registry::wasm_result::{ + get_value, get_value_call_getter, try_wasm, wasm_ok, +}; use crate::script_implementations::wasm::export_registry::{register, WasmResult}; use crate::script_implementations::wasm::extern_ref::ExternRef; use wasmer::FunctionEnvMut; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use anyhow_ext::Context; register! { fn battle_random_get( env: FunctionEnvMut, battle_random: ExternRef, ) -> WasmResult { - battle_random.value_func(&env)?.get().into() + let v = get_value_call_getter!(battle_random.get(), env); + let v = try_wasm!(v, env); + wasm_ok(v) } fn battle_random_get_max( env: FunctionEnvMut, battle_random: ExternRef, max: i32 ) -> WasmResult { - battle_random.value_func(&env)?.get_max(max).into() + let battle_random = get_value!(battle_random, env); + let v = try_wasm!(battle_random.get_max(max), env); + wasm_ok(v) } fn battle_random_get_between( env: FunctionEnvMut, @@ -25,6 +33,8 @@ register! { min: i32, max: i32 ) -> WasmResult { - battle_random.value_func(&env)?.get_between(min, max).into() + let battle_random = get_value!(battle_random, env); + let v = try_wasm!(battle_random.get_between(min, max), env); + wasm_ok(v) } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs b/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs index 7e90ab3..8089084 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs @@ -1,10 +1,13 @@ -use crate::dynamic_data::{Battle, BattleSide, Pokemon, VolatileScriptsOwner}; -use crate::script_implementations::wasm::export_registry::{register, WasmResult}; +use crate::dynamic_data::{Battle, BattleSide, Pokemon, ScriptCategory, VolatileScriptsOwner}; +use crate::script_implementations::wasm::export_registry::wasm_result::{ + get_value, get_value_call_getter, try_wasm, wasm_ok, WasmVoidResultExtension, +}; +use crate::script_implementations::wasm::export_registry::{register, wasm_err, WasmResult, WasmVoidResult}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; -use crate::ScriptCategory; use anyhow::anyhow; +use anyhow_ext::Context; use std::ffi::CStr; use wasmer::FunctionEnvMut; @@ -13,35 +16,37 @@ register! { env: FunctionEnvMut, side: ExternRef, ) -> WasmResult { - Ok(u8::from(side.value_func(&env)?.has_fled_battle())).into() + wasm_ok(u8::from(get_value_call_getter!(side.has_fled_battle(), env))) } fn battleside_is_defeated( env: FunctionEnvMut, side: ExternRef, ) -> WasmResult { - Ok(u8::from(side.value_func(&env)?.is_defeated())).into() + wasm_ok(u8::from(get_value_call_getter!(side.is_defeated(), env))) } fn battleside_get_side_index( env: FunctionEnvMut, side: ExternRef, ) -> WasmResult { - Ok(side.value_func(&env)?.index()).into() + wasm_ok(get_value_call_getter!(side.index(), env)) } fn battleside_get_pokemon_per_side( env: FunctionEnvMut, side: ExternRef, ) -> WasmResult { - Ok(side.value_func(&env)?.pokemon_per_side()).into() + wasm_ok(get_value_call_getter!(side.pokemon_per_side(), env)) } fn battleside_get_battle( env: FunctionEnvMut, side: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, side.value_func(&env)?.battle()?)).into() + let value = get_value_call_getter!(side.battle(), env); + let value = try_wasm!(value, env); + wasm_ok(ExternRef::func_new(&env, &value)) } fn battleside_get_pokemon( @@ -49,25 +54,26 @@ register! { side: ExternRef, index: u32 ) -> WasmResult> { - Ok(if let Some(Some(p)) = side.value_func(&env)?.pokemon().get(index as usize) { - ExternRef::func_new(&env, p.as_ref()) + let side = get_value!(side, env); + wasm_ok(if let Some(Some(p)) = side.pokemon().get(index as usize) { + ExternRef::::func_new(&env, p.as_ref()) } else { ExternRef::null() - }).into() + }) } fn battle_side_get_has_fled_battle( env: FunctionEnvMut, side: ExternRef, ) -> WasmResult { - Ok(if side.value_func(&env)?.has_fled_battle() { 1 } else { 0 }).into() + wasm_ok(if get_value_call_getter!(side.has_fled_battle(), env) { 1 } else { 0 }) } fn battle_side_get_is_defeated( env: FunctionEnvMut, side: ExternRef, ) -> WasmResult { - Ok(if side.value_func(&env)?.is_defeated() { 1 } else { 0 }).into() + wasm_ok(if get_value_call_getter!(side.is_defeated(), env) { 1 } else { 0 }) } fn battleside_add_volatile_by_name( @@ -76,14 +82,15 @@ register! { name_ptr: u32 ) -> WasmResult { unsafe { + let side = get_value!(side, env); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); - let script = side.value_func(&env)?.add_volatile_script(&c_name.as_ref().into())?; - Ok(if let Some(script) = script { - let script = script.get_as::()?; + let script = try_wasm!(side.add_volatile_script(&c_name.as_ref().into()), env); + wasm_ok(if let Some(script) = script { + let script = try_wasm!(script.get_as::(), env); script.get_wasm_pointer() } else { 0 - }).into() + }) } } @@ -92,27 +99,28 @@ register! { side: ExternRef, script_ptr: u32 ) -> WasmResult { - let side : &BattleSide = side.value_func(&env)?; + let side : &BattleSide = get_value!(side, env); unsafe { - let env = env.data().data(); - let name_ptr = match env - .script_function_cache() - .script_get_name(&env)? - .call(&mut env.store_mut(), script_ptr) { - Ok(name_ptr) => Ok(name_ptr), - Err(e) => Err(e.into()) - }?; - let c_name: &CStr = CStr::from_ptr(env.get_raw_pointer(name_ptr)); - let script = env.setup_script(script_ptr, ScriptCategory::Side, &c_name.as_ref().into(), side.into())?; - env.script_function_cache().dealloc_cstring(&env, name_ptr)?; + let e = env.data().data(); + let name_func = try_wasm!(e.script_function_cache().script_get_name(&e), env); + let name_ptr = try_wasm!(name_func.call(&mut e.store_mut(), script_ptr), env); + let c_name: &CStr = CStr::from_ptr(e.get_raw_pointer(name_ptr)); + let script = try_wasm!(e.setup_script(script_ptr, ScriptCategory::Side, &c_name.as_ref().into(), side.into()), env); + try_wasm!(e.script_function_cache().dealloc_cstring(&e, name_ptr), env); - Ok(if let Some(script) = script { - let script = side.add_volatile_script_with_script(script)?; - let s = script.as_ref().ok_or(anyhow!("Couldn't get script"))?.get_as::()?; - s.get_wasm_pointer() + if let Some(script) = script { + let script = try_wasm!(side.add_volatile_script_with_script(script), env); + let script = script.as_ref(); + match script { + Some(script) => { + let script = try_wasm!(script.get_as::(), env); + wasm_ok(script.get_wasm_pointer()) + }, + None => wasm_err::(anyhow!("Couldn't get script"), &env) + } } else { - 0 - }).into() + wasm_ok(0) + } } } @@ -122,8 +130,9 @@ register! { name_ptr: u32 ) -> WasmResult { unsafe { + let side = get_value!(side, env); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); - Ok(u8::from(side.value_func(&env)?.has_volatile_script(&c_name.as_ref().into()))).into() + wasm_ok(u8::from(side.has_volatile_script(&c_name.as_ref().into()))) } } @@ -133,14 +142,15 @@ register! { name_ptr: u32 ) -> WasmResult { unsafe { + let side = get_value!(side, env); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); - let script = side.value_func(&env)?.get_volatile_script(&c_name.as_ref().into()); - Ok(if let Some(script) = script { - let script = script.get_as::()?; - script.get_wasm_pointer() + let script = side.get_volatile_script(&c_name.as_ref().into()); + if let Some(script) = script { + let script = try_wasm!(script.get_as::(), env); + wasm_ok(script.get_wasm_pointer()) } else { - 0 - }).into() + wasm_ok(0) + } } } @@ -148,10 +158,17 @@ register! { env: FunctionEnvMut, side: ExternRef, name_ptr: u32 - ) -> WasmResult<()> { + ) -> WasmVoidResult { unsafe { + let side = match side.value_func(&env) { + Ok(side) => side, + Err(e) => return WasmVoidResult::err(e, &env) + }; let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); - side.value_func(&env)?.remove_volatile_script(&c_name.as_ref().into()).into() + match side.remove_volatile_script(&c_name.as_ref().into()) { + Ok(_) => WasmVoidResult::ok(), + Err(e) => WasmVoidResult::err(e, &env) + } } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/choice_queue.rs b/src/script_implementations/wasm/export_registry/dynamic_data/choice_queue.rs index c1f8c56..2b5a57e 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/choice_queue.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/choice_queue.rs @@ -1,7 +1,8 @@ use crate::dynamic_data::{ChoiceQueue, Pokemon}; -use crate::script_implementations::wasm::export_registry::{register, WasmResult}; +use crate::script_implementations::wasm::export_registry::{get_value, register, try_wasm, wasm_ok, WasmResult}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use anyhow_ext::Context; use wasmer::FunctionEnvMut; register! { @@ -10,6 +11,9 @@ register! { battle_random: ExternRef, pokemon: ExternRef ) -> WasmResult { - Ok(u8::from(battle_random.value_func(&env)?.move_pokemon_choice_next(pokemon.value_func(&env)?)?)).into() + let battle_random = get_value!(battle_random, env); + let pokemon = get_value!(pokemon, env); + let res = try_wasm!(battle_random.move_pokemon_choice_next(pokemon), env); + wasm_ok(u8::from(res)) } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs b/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs index 6b59213..68aa902 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs @@ -1,9 +1,13 @@ use crate::dynamic_data::{ExecutingMove, HitData, LearnedMove, Pokemon}; -use crate::script_implementations::wasm::export_registry::{register, WasmResult}; +use crate::script_implementations::wasm::export_registry::wasm_result::get_value_arc; +use crate::script_implementations::wasm::export_registry::{ + get_value, get_value_call_getter, register, try_wasm, wasm_ok, WasmResult, +}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::MoveData; +use anyhow_ext::Context; use wasmer::FunctionEnvMut; register! { @@ -11,28 +15,31 @@ register! { env: FunctionEnvMut, executing_move: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.user().as_ref())).into() + let user = get_value_call_getter!(executing_move.user(), env); + wasm_ok(ExternRef::::func_new(&env, user.as_ref())) } fn executing_move_get_use_move( env: FunctionEnvMut, executing_move: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.use_move())).into() + let use_move = get_value_call_getter!(executing_move.use_move(), env); + wasm_ok(ExternRef::::func_new(&env, use_move)) } fn executing_move_get_chosen_move( env: FunctionEnvMut, executing_move: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.chosen_move().as_ref())).into() + let chosen_move = get_value_call_getter!(executing_move.chosen_move(), env); + wasm_ok(ExternRef::::func_new(&env, chosen_move.as_ref())) } fn executing_move_get_number_of_hits( env: FunctionEnvMut, executing_move: ExternRef, ) -> WasmResult { - Ok(executing_move.value_func(&env)?.number_of_hits()).into() + wasm_ok(get_value_call_getter!(executing_move.number_of_hits(), env)) } fn executing_move_get_hit_data( @@ -41,14 +48,17 @@ register! { target: ExternRef, hit: u8 ) -> WasmResult> { - Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.get_hit_data(target.value_func(&env)?, hit)?)).into() + let executing_move = get_value!(executing_move, env); + let target = get_value_arc!(target, env); + let hit_data = try_wasm!(executing_move.get_hit_data(&target, hit), env); + wasm_ok(ExternRef::::func_new(&env, hit_data)) } fn executing_move_get_number_of_targets( env: FunctionEnvMut, executing_move: ExternRef, ) -> WasmResult { - Ok(executing_move.value_func(&env)?.target_count() as u32).into() + wasm_ok(get_value_call_getter!(executing_move.target_count(), env) as u32) } fn executing_move_is_pokemon_target( @@ -56,8 +66,9 @@ register! { executing_move: ExternRef, pokemon: ExternRef ) -> WasmResult { - let pokemon = pokemon.value_func_arc(&env)?; - Ok(if executing_move.value_func(&env)?.is_pokemon_target(&pokemon) { 1 } else { 0 }).into() + let executing_move = get_value!(executing_move, env); + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(if executing_move.is_pokemon_target(&pokemon) { 1 } else { 0 }) } @@ -65,14 +76,15 @@ register! { fn executing_move_get_script( env: FunctionEnvMut, executing_move: ExternRef, - ) -> WasmResult<(u32 , u32)> { - let executing_move = executing_move.value_func(&env)?; + ) -> WasmResult { + let executing_move = get_value!(executing_move, env); let script = executing_move.script(); if script.is_any() { - let s = script.get_as::()?.get_wasm_pointer(); - return Ok((s, s + 4)).into() + let script = try_wasm!(script.get_as::(), env); + let s = script.get_wasm_pointer(); + return wasm_ok(s) } - Ok((0, 0)).into() + wasm_ok(0u32) } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs b/src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs index cffcf17..c42a37d 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs @@ -1,82 +1,97 @@ use crate::dynamic_data::HitData; -use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::export_registry::wasm_result::{ + get_value_call_getter, get_value_void, wasm_ok, WasmVoidResultExtension, +}; +use crate::script_implementations::wasm::export_registry::{register, WasmResult, WasmVoidResult}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use anyhow_ext::Context; use wasmer::FunctionEnvMut; register! { fn hit_data_get_damage( env: FunctionEnvMut, hit: ExternRef, - ) -> u32 { - hit.value_func(&env).unwrap().damage() + ) -> WasmResult { + wasm_ok(get_value_call_getter!(hit.damage(), env)) } fn hit_data_is_critical( env: FunctionEnvMut, hit: ExternRef, - ) -> u8 { - u8::from(hit.value_func(&env).unwrap().is_critical()) + ) -> WasmResult { + let is_critical = get_value_call_getter!(hit.is_critical(), env); + wasm_ok(u8::from(is_critical)) } fn hit_data_fail( env: FunctionEnvMut, hit: ExternRef, - ) { - hit.value_func(&env).unwrap().fail() + ) -> WasmVoidResult { + let hit = get_value_void!(hit, env); + hit.fail(); + WasmVoidResult::ok() } fn hit_data_get_base_power( env: FunctionEnvMut, hit: ExternRef, - ) -> u8 { - hit.value_func(&env).unwrap().base_power() + ) -> WasmResult { + wasm_ok(get_value_call_getter!(hit.base_power(), env)) } fn hit_data_get_effectiveness( env: FunctionEnvMut, hit: ExternRef, - ) -> f32 { - hit.value_func(&env).unwrap().effectiveness() + ) -> WasmResult { + wasm_ok(get_value_call_getter!(hit.effectiveness(), env)) } fn hit_data_get_move_type( env: FunctionEnvMut, hit: ExternRef, - ) -> u8 { - hit.value_func(&env).unwrap().move_type().into() + ) -> WasmResult { + wasm_ok(get_value_call_getter!(hit.move_type(), env).into()) } fn hit_data_set_critical( env: FunctionEnvMut, hit: ExternRef, value: u8 - ) { - hit.value_func(&env).unwrap().set_critical(value == 1) + ) -> WasmVoidResult { + let hit = get_value_void!(hit, env); + hit.set_critical(value == 1); + WasmVoidResult::ok() } fn hit_data_set_effectiveness( env: FunctionEnvMut, hit: ExternRef, effectiveness: f32 - ) { - hit.value_func(&env).unwrap().set_effectiveness(effectiveness) + ) -> WasmVoidResult { + let hit = get_value_void!(hit, env); + hit.set_effectiveness(effectiveness); + WasmVoidResult::ok() } fn hit_data_set_damage( env: FunctionEnvMut, hit: ExternRef, damage: u32 - ) { - hit.value_func(&env).unwrap().set_damage(damage) + ) -> WasmVoidResult { + let hit = get_value_void!(hit, env); + hit.set_damage(damage); + WasmVoidResult::ok() } fn hit_data_set_move_type( env: FunctionEnvMut, hit: ExternRef, move_type: u8 - ) { - hit.value_func(&env).unwrap().set_move_type(move_type.into()) + ) -> WasmVoidResult { + let hit = get_value_void!(hit, env); + hit.set_move_type(move_type.into()); + WasmVoidResult::ok() } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs b/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs index 82aef96..3f1e39f 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs @@ -1,42 +1,52 @@ use std::intrinsics::transmute; -use crate::dynamic_data::LearnedMove; -use crate::script_implementations::wasm::export_registry::register; +use crate::dynamic_data::{LearnedMove, MoveLearnMethod}; +use crate::script_implementations::wasm::export_registry::wasm_result::{ + get_value_call_getter, get_value_void, wasm_ok, WasmVoidResult, WasmVoidResultExtension, +}; +use crate::script_implementations::wasm::export_registry::{register, WasmResult}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::MoveData; +use anyhow_ext::Context; use wasmer::FunctionEnvMut; register! { fn learned_move_get_learn_method( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> u8 { + ) -> WasmResult { unsafe { - transmute(turn_choice.value_func(&env).unwrap().learn_method()) + let learn_method = get_value_call_getter!(turn_choice.learn_method(), &env); + wasm_ok(transmute::(learn_method)) } } fn learned_move_get_move_data( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> ExternRef { - ExternRef::func_new(&env, turn_choice.value_func(&env).unwrap().move_data()) + ) -> WasmResult> { + let move_data = get_value_call_getter!(turn_choice.move_data(), &env); + wasm_ok(ExternRef::::func_new(&env, move_data)) } fn learned_move_restore_all_uses( env: FunctionEnvMut, turn_choice: ExternRef, - ) { - turn_choice.value_func(&env).unwrap().restore_all_uses(); + ) -> WasmVoidResult { + let turn_choice = get_value_void!(turn_choice, env); + turn_choice.restore_all_uses(); + WasmVoidResult::ok() } fn learned_move_restore_uses( env: FunctionEnvMut, turn_choice: ExternRef, amount: u8, - ) { - turn_choice.value_func(&env).unwrap().restore_uses(amount).unwrap(); + ) -> WasmVoidResult { + let turn_choice = get_value_void!(turn_choice, env); + turn_choice.restore_uses(amount); + WasmVoidResult::ok() } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs b/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs index b028bb2..33db355 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs @@ -1,11 +1,13 @@ use crate::dynamic_data::{DynamicLibrary, ScriptOwnerData}; use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::export_registry::wasm_result::{try_wasm, wasm_ok, WasmResult}; use crate::script_implementations::wasm::extern_ref::ExternRef; use std::sync::atomic::Ordering; use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut}; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::StaticData; +use anyhow_ext::Context; /// The battle registration mod battle; @@ -32,8 +34,10 @@ register! { fn dynamic_library_get_static_data( env: FunctionEnvMut, dynamic_lib: ExternRef, - ) -> ExternRef { - ExternRef::func_new(&env, dynamic_lib.value_func_arc(&env).unwrap().static_data()) + ) -> WasmResult> { + let dynamic_lib = try_wasm!(dynamic_lib.value_func_arc(&env), env); + let static_data = dynamic_lib.static_data(); + wasm_ok(ExternRef::::func_new(&env, static_data)) } fn script_get_owner( diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/party.rs b/src/script_implementations/wasm/export_registry/dynamic_data/party.rs index b205c20..797d3ab 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/party.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/party.rs @@ -1,7 +1,9 @@ use crate::dynamic_data::{Pokemon, PokemonParty}; use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::export_registry::wasm_result::{get_value, wasm_ok, WasmResult}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use anyhow_ext::Context; use wasmer::FunctionEnvMut; register! { @@ -9,18 +11,21 @@ register! { env: FunctionEnvMut, party: ExternRef, index: u32 - ) -> ExternRef { - if let Some(v) = &party.value_func(&env).unwrap().pokemon()[index as usize] { + ) -> WasmResult> { + let party = get_value!(party, env); + wasm_ok( + if let Some(Some(v)) = &party.pokemon().get(index as usize) { ExternRef::func_new(&env, v.as_ref()) } else { ExternRef::null() - } + }) } fn party_get_length( env: FunctionEnvMut, party: ExternRef, - ) -> u32 { - party.value_func(&env).unwrap().length() as u32 + ) -> WasmResult { + let party = get_value!(party, env); + wasm_ok(party.length() as u32) } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs b/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs index 6f069b1..5a7cc12 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs @@ -2,7 +2,10 @@ use std::mem::transmute; use crate::defines::LevelInt; use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner}; -use crate::script_implementations::wasm::export_registry::{register, WasmResult}; +use crate::script_implementations::wasm::export_registry::{ + get_value_arc, get_value_arc_void, get_value_call_getter, get_value_void, register, try_wasm, wasm_err, wasm_ok, + WasmResult, WasmVoidResult, WasmVoidResultExtension, +}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; @@ -10,6 +13,7 @@ use crate::static_data::{Ability, ClampedStatisticSet, Form, Nature, Species}; use crate::static_data::{Item, StatisticSet}; use crate::{ScriptCategory, VecExt}; use anyhow::anyhow; +use anyhow_ext::Context; use std::ffi::{c_char, CStr, CString}; use wasmer::FunctionEnvMut; @@ -18,72 +22,76 @@ register! { env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - let lib = pokemon.value_func(&env)?.library().clone(); - Ok(ExternRef::func_new(&env, &lib)).into() + let lib = get_value_call_getter!(pokemon.library(), env).clone(); + wasm_ok(ExternRef::::func_new(&env, &lib)) } fn pokemon_get_boosted_stats( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult>> { - let statistic_set = pokemon.value_func(&env)?.boosted_stats(); - Ok(ExternRef::func_new(&env, statistic_set)).into() + let statistic_set = get_value_call_getter!(pokemon.boosted_stats(), env).clone(); + wasm_ok(ExternRef::>::func_new(&env, statistic_set)) } fn pokemon_get_flat_stats( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult>> { - let statistic_set = pokemon.value_func(&env)?.flat_stats(); - Ok(ExternRef::func_new(&env, statistic_set)).into() + let statistic_set = get_value_call_getter!(pokemon.flat_stats(), env).clone(); + wasm_ok(ExternRef::>::func_new(&env, statistic_set)) } fn pokemon_get_stat_boosts( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult>> { - let statistic_set = pokemon.value_func(&env)?.stat_boosts(); - Ok(ExternRef::func_new(&env, statistic_set)).into() + let statistic_set = get_value_call_getter!(pokemon.stat_boosts(), env).clone(); + wasm_ok(ExternRef::>::func_new(&env, statistic_set)) } fn pokemon_get_individual_values( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult>> { - let statistic_set = pokemon.value_func(&env)?.individual_values(); - Ok(ExternRef::func_new(&env, statistic_set)).into() + let statistic_set = get_value_call_getter!(pokemon.individual_values(), env).clone(); + wasm_ok(ExternRef::>::func_new(&env, statistic_set)) } fn pokemon_get_effort_values( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult>> { - let statistic_set = pokemon.value_func(&env)?.effort_values(); - Ok(ExternRef::func_new(&env, statistic_set)).into() + let statistic_set = get_value_call_getter!(pokemon.effort_values(), env).clone(); + wasm_ok(ExternRef::>::func_new(&env, statistic_set)) } fn pokemon_get_species( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - let species = pokemon.value_func(&env)?.species(); - Ok(ExternRef::func_new(&env, &species)).into() + let species = get_value_call_getter!(pokemon.species(), env).clone(); + wasm_ok(ExternRef::::func_new(&env, &species)) } fn pokemon_get_weight( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(pokemon.value_func(&env)?.weight()).into() + wasm_ok(get_value_call_getter!(pokemon.weight(), env)) } fn pokemon_set_weight( env: FunctionEnvMut, pokemon: ExternRef, weight: f32, - ) -> WasmResult<()> { - pokemon.value_func(&env)?.set_weight(weight); - Ok(()).into() + ) -> WasmVoidResult { + let pokemon = match pokemon.value_func(&env) { + Ok(pokemon) => pokemon, + Err(e) => return WasmVoidResult::err(e, &env), + }; + pokemon.set_weight(weight); + WasmVoidResult::ok() } @@ -91,7 +99,7 @@ register! { env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(pokemon.value_func(&env)?.height()).into() + wasm_ok(get_value_call_getter!(pokemon.height(), env)) } fn pokemon_get_gender( @@ -99,7 +107,7 @@ register! { pokemon: ExternRef, ) -> WasmResult { unsafe { - Ok(transmute(pokemon.value_func(&env)?.gender())).into() + wasm_ok(transmute(get_value_call_getter!(pokemon.gender(), env))) } } @@ -108,10 +116,16 @@ register! { pokemon: ExternRef, damage: u32, source: u8 - ) -> WasmResult<()> { - unsafe{ - pokemon.value_func(&env)?.damage(damage, transmute(source))?; - WasmResult::ok(()) + ) -> WasmVoidResult { + unsafe { + let pokemon = match pokemon.value_func(&env) { + Ok(pokemon) => pokemon, + Err(e) => return WasmVoidResult::err(e, &env), + }; + match pokemon.damage(damage, transmute(source)) { + Ok(()) => WasmVoidResult::ok(), + Err(e) => WasmVoidResult::err(e, &env), + } } } @@ -120,14 +134,15 @@ register! { pokemon: ExternRef, index: u32 ) -> WasmResult> { - let read_lock = pokemon.value_func(&env)?.learned_moves().read(); + let pokemon = get_value_arc!(pokemon, env); + let read_lock = pokemon.learned_moves().read(); let mv = read_lock.get(index as usize); - Ok(if let Some(Some(mv)) = mv { - ExternRef::func_new(&env, mv) + wasm_ok(if let Some(Some(mv)) = mv { + ExternRef::::func_new(&env, mv) } else{ - ExternRef::null() - }).into() + ExternRef::::null() + }) } fn pokemon_change_stat_boost( @@ -138,7 +153,9 @@ register! { self_inflicted: u8 ) -> WasmResult { unsafe{ - Ok(u8::from(pokemon.value_func(&env)?.change_stat_boost(transmute(stat), amount, self_inflicted == 1)?)).into() + let pokemon = get_value_arc!(pokemon, env); + let res = try_wasm!(pokemon.change_stat_boost(transmute(stat), amount, self_inflicted == 1), env); + wasm_ok(u8::from(res)) } } @@ -146,45 +163,51 @@ register! { env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - Ok(if let Some(battle) = pokemon.value_func(&env)?.get_battle() { - ExternRef::func_new(&env, battle) + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(if let Some(battle) = pokemon.get_battle() { + let r = ExternRef::func_new(&env, &battle); + std::mem::forget(battle); + r } else { ExternRef::null() - }).into() + }) } fn pokemon_get_battle_index( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(if let Some(i) = pokemon.value_func(&env)?.get_battle_index() { + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(if let Some(i) = pokemon.get_battle_index() { i } else { 255 - }).into() + }) } fn pokemon_get_battle_side_index( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(if let Some(i) = pokemon.value_func(&env)?.get_battle_side_index() { + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(if let Some(i) = pokemon.get_battle_side_index() { i } else { 255 - }).into() + }) } fn pokemon_get_held_item( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - let read_lock = pokemon.value_func(&env)?.held_item().read(); - Ok(if let Some(item) = read_lock.as_ref() { - ExternRef::func_new(&env, item.as_ref()) + let pokemon = get_value_arc!(pokemon, env); + let read_lock = pokemon.held_item().read(); + wasm_ok(if let Some(item) = read_lock.as_ref() { + ExternRef::::func_new(&env, item.as_ref()) } else { - ExternRef::null() - }).into() + ExternRef::::null() + }) } fn pokemon_has_held_item( @@ -194,7 +217,8 @@ register! { ) -> WasmResult { let name : *mut c_char = env.data().data().get_raw_pointer(name); let name = unsafe { CStr::from_ptr(name) }; - Ok(u8::from(pokemon.value_func(&env)?.has_held_item(&name.into()))).into() + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(u8::from(pokemon.has_held_item(&name.into()))) } fn pokemon_heal( @@ -203,51 +227,62 @@ register! { amount: u32, allow_revive: u8 ) -> WasmResult { - Ok(u8::from(pokemon.value_func(&env)?.heal(amount, allow_revive == 1))).into() + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(u8::from(pokemon.heal(amount, allow_revive == 1))) } fn pokemon_clear_status( env: FunctionEnvMut, pokemon: ExternRef, - ) -> WasmResult<()> { - pokemon.value_func(&env)?.clear_status(); - WasmResult::ok(()) + ) -> WasmVoidResult { + let pokemon = match pokemon.value_func(&env) { + Ok(pokemon) => pokemon, + Err(e) => return WasmVoidResult::err(e, &env), + }; + pokemon.clear_status(); + WasmVoidResult::ok() } fn pokemon_get_active_ability( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.active_ability())).into() + let active_ability = get_value_call_getter!(pokemon.active_ability(), env); + wasm_ok(ExternRef::::func_new(&env, &active_ability)) } fn pokemon_get_real_ability( env: FunctionEnvMut, pokemon: ExternRef, - ) -> WasmResult<(u8, u8)> { - let index = &pokemon.value_func(&env)?.real_ability(); - WasmResult::ok((if index.hidden { 1 } else { 0 }, index.index)) + ) -> WasmResult { + let index = get_value_call_getter!(pokemon.real_ability(), env); + let t: (u8, u8) = (if index.hidden { 1 } else { 0 }, index.index); + let r: u16 = unsafe { transmute(t) }; + wasm_ok(r) } fn pokemon_get_is_ability_overriden( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(if pokemon.value_func(&env)?.is_ability_overriden() { 1 } else { 0 }).into() + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(if pokemon.is_ability_overriden() { 1 } else { 0 }) } fn pokemon_get_allowed_experience_gain( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(if pokemon.value_func(&env)?.allowed_experience_gain() { 1 } else { 0 }).into() + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(if pokemon.allowed_experience_gain() { 1 } else { 0 }) } fn pokemon_get_is_usable( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(if pokemon.value_func(&env)?.is_usable() { 1 } else { 0 }).into() + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(if pokemon.is_usable() { 1 } else { 0 }) } @@ -256,39 +291,45 @@ register! { pokemon: ExternRef, item: ExternRef ) -> WasmResult> { - let item = item.value_func_arc(&env)?; - let old_item = pokemon.value_func(&env)?.set_held_item(&item); - Ok(if let Some(old_item) = old_item { - ExternRef::func_new(&env, &old_item) + let item = get_value_arc!(item, env); + let pokemon = get_value_arc!(pokemon, env); + let old_item = pokemon.set_held_item(&item); + wasm_ok(if let Some(old_item) = old_item { + ExternRef::::func_new(&env, &old_item) } else { ExternRef::null() - }).into() + }) } fn pokemon_remove_held_item( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - let old_item = pokemon.value_func(&env)?.remove_held_item(); - Ok(if let Some(old_item) = old_item { - ExternRef::func_new(&env, &old_item) + let pokemon = get_value_arc!(pokemon, env); + let old_item = pokemon.remove_held_item(); + wasm_ok(if let Some(old_item) = old_item { + ExternRef::::func_new(&env, &old_item) } else { - ExternRef::null() - }).into() + ExternRef::::null() + }) } fn pokemon_consume_held_item( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(if pokemon.value_func(&env)?.consume_held_item()? { 1 } else { 0 }).into() + let pokemon = get_value_arc!(pokemon, env); + let res = try_wasm!(pokemon.consume_held_item(), env); + wasm_ok(if res { 1 } else { 0 }) } fn pokemon_get_types_length( env: FunctionEnvMut, pokemon: ExternRef ) -> WasmResult { - Ok(pokemon.value_func(&env)?.types().len() as u32).into() + let pokemon = get_value_arc!(pokemon, env); + let len = pokemon.types().len(); + wasm_ok(len as u32) } fn pokemon_get_type( @@ -296,7 +337,13 @@ register! { pokemon: ExternRef, index: u32 ) -> WasmResult { - Ok((*pokemon.value_func(&env)?.types().get_res(index as usize)?).into()).into() + let pokemon = get_value_arc!(pokemon, env); + let types = pokemon.types(); + let type_v = types.get_res(index as usize); + match type_v { + Ok(t) => wasm_ok(u8::from(*t)), + Err(e) => wasm_err::(e, &env), + } } fn pokemon_has_type( @@ -304,7 +351,8 @@ register! { pokemon: ExternRef, t: u8 ) -> WasmResult { - Ok(if pokemon.value_func(&env)?.types().contains(&t.into()) { 1 } else { 0 }).into() + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(if pokemon.types().contains(&t.into()) { 1 } else { 0 }) } fn pokemon_change_species( @@ -312,102 +360,117 @@ register! { pokemon: ExternRef, species: ExternRef, form: ExternRef, - ) -> WasmResult<()> { - pokemon.value_func(&env)?.change_species( - species.value_func_arc(&env)?, - form.value_func_arc(&env)?, - )?; - WasmResult::ok(()) + ) -> WasmVoidResult { + let pokemon = get_value_void!(pokemon, env); + let species = get_value_arc_void!(species, env); + let form = get_value_arc_void!(form, env); + + match pokemon.change_species( + species, + form, + ) { + Ok(_) => WasmVoidResult::ok(), + Err(e) => WasmVoidResult::err(e, &env), + } } fn pokemon_change_form( env: FunctionEnvMut, pokemon: ExternRef, form: ExternRef, - ) -> WasmResult<()> { - pokemon.value_func(&env)?.change_form( - &form.value_func_arc(&env)?, - )?; - WasmResult::ok(()) + ) -> WasmVoidResult { + let pokemon = get_value_void!(pokemon, env); + let form = get_value_arc_void!(form, env); + match pokemon.change_form(&form) { + Ok(_) => WasmVoidResult::ok(), + Err(e) => WasmVoidResult::err(e, &env), + } } fn pokemon_get_current_health( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(pokemon.value_func(&env)?.current_health()).into() + wasm_ok(get_value_call_getter!(pokemon.current_health(), env)) } fn pokemon_get_nature( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, pokemon.value_func(&env)?.nature())).into() + let nature = get_value_call_getter!(pokemon.nature(), env); + wasm_ok(ExternRef::::func_new(&env, nature)) } fn pokemon_get_form( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.form())).into() + let form = get_value_call_getter!(pokemon.form(), env); + wasm_ok(ExternRef::::func_new(&env, &form)) } fn pokemon_get_display_species( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.display_species())).into() + let display_species = get_value_call_getter!(pokemon.display_species(), env); + wasm_ok(ExternRef::::func_new(&env, &display_species)) } fn pokemon_get_display_form( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult> { - Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.display_form())).into() + let display_form = get_value_call_getter!(pokemon.display_form(), env); + wasm_ok(ExternRef::::func_new(&env, &display_form)) } fn pokemon_get_level( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(pokemon.value_func(&env)?.level()).into() + wasm_ok(get_value_call_getter!(pokemon.level(), env)) } fn pokemon_get_experience( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(pokemon.value_func(&env)?.experience()).into() + wasm_ok(get_value_call_getter!(pokemon.experience(), env)) } fn pokemon_get_unique_identifier( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(pokemon.value_func(&env)?.unique_identifier()).into() + wasm_ok(get_value_call_getter!(pokemon.unique_identifier(), env)) } fn pokemon_get_coloring( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - Ok(pokemon.value_func(&env)?.coloring()).into() + wasm_ok(get_value_call_getter!(pokemon.coloring(), env)) } fn pokemon_get_nickname( env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - let pokemon = pokemon.value_func(&env)?; + let pokemon = get_value_arc!(pokemon, env); let nickname = pokemon.nickname(); if let Some(nickname) = nickname { let nickname: CString = match CString::new(nickname.as_str()) { Ok(nickname) => nickname, - Err(e) => return WasmResult::err(e.into()), + Err(e) => return wasm_err::(e.into(), &env), }; - env.data().data().copy_value_vec_to_wasm(nickname.as_bytes()).into() + match env.data().data().copy_value_vec_to_wasm(nickname.as_bytes()) { + Ok(ptr) => wasm_ok(ptr), + Err(e) => wasm_err::(e, &env), + } } else { - Ok(0).into() + wasm_ok(0) } } @@ -419,13 +482,14 @@ register! { name_ptr: u32 ) -> WasmResult { unsafe { + let pokemon = get_value_arc!(pokemon, env); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); - let script = pokemon.value_func(&env)?.add_volatile_script(&c_name.as_ref().into())?; + let script = try_wasm!(pokemon.add_volatile_script(&c_name.as_ref().into()), env); if let Some(script) = script { - let script = script.get_as::()?; - Ok(script.get_wasm_pointer()).into() + let script = try_wasm!(script.get_as::(), env); + wasm_ok(script.get_wasm_pointer()) } else { - Ok(0).into() + wasm_ok(0) } } } @@ -435,23 +499,27 @@ register! { pokemon: ExternRef, script_ptr: u32 ) -> WasmResult { - let pokemon : &Pokemon = pokemon.value_func(&env)?; + let pokemon = get_value_arc!(pokemon, env); unsafe{ - let env = env.data().data(); - let name_ptr = match env.script_function_cache().script_get_name(&env)?.call(&mut env.store_mut(), script_ptr){ + let env_data = env.data().data(); + let name_ptr = match try_wasm!(env_data.script_function_cache().script_get_name(&env_data), env).call(&mut env_data.store_mut(), script_ptr){ Ok(name_ptr) => name_ptr, - Err(e) => return WasmResult::err(e.into()) + Err(e) => return wasm_err::(e.into(), &env) }; - let c_name: &CStr = CStr::from_ptr(env.get_raw_pointer(name_ptr)); - let script = env.setup_script(script_ptr, ScriptCategory::Pokemon, &c_name.as_ref().into(), pokemon.into())?; - env.script_function_cache().dealloc_cstring(&env, name_ptr)?; + let c_name: &CStr = CStr::from_ptr(env_data.get_raw_pointer(name_ptr)); + let script = try_wasm!(env_data.setup_script(script_ptr, ScriptCategory::Pokemon, &c_name.as_ref().into(), pokemon.as_ref().into()), env); + try_wasm!(env_data.script_function_cache().dealloc_cstring(&env_data, name_ptr), env); if let Some(script) = script { - let script = pokemon.add_volatile_script_with_script(script)?; - let s = script.as_ref().ok_or(anyhow!("Unable to get script"))?.get_as::()?; - WasmResult::ok(s.get_wasm_pointer()) + let script = try_wasm!(pokemon.add_volatile_script_with_script(script), env); + let s = match script.as_ref() { + Some(s) => s, + None => return wasm_err::(anyhow!("Unable to get script").into(), &env) + }; + let s = try_wasm!(s.get_as::(), env); + wasm_ok(s.get_wasm_pointer()) } else { - WasmResult::ok(0) + wasm_ok(0) } } } @@ -463,7 +531,8 @@ register! { ) -> WasmResult { unsafe { let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); - Ok(u8::from(pokemon.value_func(&env)?.has_volatile_script(&c_name.as_ref().into()))).into() + let pokemon = get_value_arc!(pokemon, env); + wasm_ok(u8::from(pokemon.has_volatile_script(&c_name.as_ref().into()))) } } @@ -474,13 +543,14 @@ register! { ) -> WasmResult { unsafe { let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); - let script = pokemon.value_func(&env)?.get_volatile_script(&c_name.as_ref().into()); - Ok(if let Some(script) = script { - let script = script.get_as::()?; + let pokemon = get_value_arc!(pokemon, env); + let script = pokemon.get_volatile_script(&c_name.as_ref().into()); + wasm_ok(if let Some(script) = script { + let script = try_wasm!(script.get_as::(), env); script.get_wasm_pointer() } else { 0 - }).into() + }) } } @@ -488,11 +558,14 @@ register! { env: FunctionEnvMut, pokemon: ExternRef, name_ptr: u32 - ) -> WasmResult<()> { + ) -> WasmVoidResult { unsafe { let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); - pokemon.value_func(&env)?.remove_volatile_script(&c_name.as_ref().into())?; - WasmResult::ok(()) + let pokemon = get_value_void!(pokemon, env); + match pokemon.remove_volatile_script(&c_name.as_ref().into()) { + Ok(_) => WasmVoidResult::ok(), + Err(e) => WasmVoidResult::err(e.into(), &env) + } } } @@ -500,12 +573,13 @@ register! { env: FunctionEnvMut, pokemon: ExternRef, ) -> WasmResult { - let pokemon = pokemon.value_func(&env)?; + let pokemon = get_value_arc!(pokemon, env); let script = pokemon.ability_script(); if script.is_any() { - return Ok(script.get_as::()?.get_wasm_pointer()).into(); + let script = try_wasm!(script.get_as::(), env); + return wasm_ok(script.get_wasm_pointer()); } - WasmResult::ok(0) + wasm_ok(0) } } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/turn_choice.rs b/src/script_implementations/wasm/export_registry/dynamic_data/turn_choice.rs index 5cca35b..ac73c72 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/turn_choice.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/turn_choice.rs @@ -1,10 +1,14 @@ -use std::ops::Deref; - use crate::dynamic_data::{LearnedMove, Pokemon, TurnChoice}; -use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::export_registry::wasm_result::{ + get_value, get_value_call_getter, get_value_void, wasm_err, +}; +use crate::script_implementations::wasm::export_registry::{ + register, wasm_ok, WasmResult, WasmVoidResult, WasmVoidResultExtension, +}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use anyhow_ext::Context; use wasmer::FunctionEnvMut; register! { @@ -12,100 +16,132 @@ register! { fn turn_choice_get_user( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> ExternRef { - let turn_choice = turn_choice.value_func(&env).unwrap(); - ExternRef::func_new(&env, turn_choice.user().as_ref().deref()) + ) -> WasmResult> { + let user = get_value_call_getter!(turn_choice.user(), &env); + wasm_ok(ExternRef::func_new(&env, user)) } fn turn_choice_get_kind( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> u8 { - match turn_choice.value_func(&env).unwrap() { + ) -> WasmResult { + let turn_choice = get_value!(turn_choice, env); + wasm_ok(match turn_choice { TurnChoice::Move(_) => 0, TurnChoice::Item(_) => 1, TurnChoice::Switch(_) => 2, TurnChoice::Flee(_) => 3, TurnChoice::Pass(_) => 4, - } + }) } fn turn_choice_get_speed( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> u32 { - turn_choice.value_func(&env).unwrap().speed() + ) -> WasmResult { + wasm_ok(get_value_call_getter!(turn_choice.speed(), &env)) } fn turn_choice_has_failed( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> u8 { - if turn_choice.value_func(&env).unwrap().has_failed() { 1 } else { 0 } + ) -> WasmResult { + wasm_ok(if get_value_call_getter!(turn_choice.has_failed(), &env) { 1 } else { 0 }) } fn turn_choice_fail( env: FunctionEnvMut, turn_choice: ExternRef, - ) { - turn_choice.value_func(&env).unwrap().fail(); + ) -> WasmVoidResult { + let turn_choice = get_value_void!(turn_choice, env); + turn_choice.fail(); + WasmVoidResult::ok() } fn turn_choice_move_priority( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> i8 { - if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() { - return d.priority() + ) -> WasmResult { + return match turn_choice.value_func(&env) { + Ok(v) => { + match v { + TurnChoice::Move(m) => wasm_ok(m.priority()), + _ => wasm_err::(anyhow_ext::anyhow!("Invalid turn choice"), &env) + } + }, + Err(e) => wasm_err::(e, &env), } - panic!("Invalid turn choice"); } fn turn_choice_move_used_move( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> ExternRef { - if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() { - return ExternRef::func_new(&env, d.used_move().as_ref()); + ) -> WasmResult> { + return match turn_choice.value_func(&env) { + Ok(v) => { + match v { + TurnChoice::Move(m) => wasm_ok(ExternRef::::func_new(&env, m.used_move())), + _ => wasm_err::>(anyhow_ext::anyhow!("Invalid turn choice"), &env) + } + }, + Err(e) => wasm_err::>(e, &env), } - panic!("Invalid turn choice"); } fn turn_choice_move_target_side( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> u8 { - if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() { - return d.target_side(); + ) -> WasmResult { + return match turn_choice.value_func(&env) { + Ok(v) => { + match v { + TurnChoice::Move(m) => wasm_ok(m.target_side()), + _ => wasm_err::(anyhow_ext::anyhow!("Invalid turn choice"), &env) + } + }, + Err(e) => wasm_err::(e, &env), } - panic!("Invalid turn choice"); } fn turn_choice_move_target_index( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> u8 { - if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() { - return d.target_index(); + ) -> WasmResult { + return match turn_choice.value_func(&env) { + Ok(v) => { + match v { + TurnChoice::Move(m) => wasm_ok(m.target_index()), + _ => wasm_err::(anyhow_ext::anyhow!("Invalid turn choice"), &env) + } + }, + Err(e) => wasm_err::(e, &env), } - panic!("Invalid turn choice"); } fn turn_choice_move_script( env: FunctionEnvMut, turn_choice: ExternRef, - ) -> u32 { - if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() { - if let Some(script) = d.script().get() { - let read_lock = script.read(); - if let Some(script) = read_lock.as_ref() { - return script.as_any().downcast_ref::().unwrap().get_wasm_pointer() + ) -> WasmResult { + return match turn_choice.value_func(&env) { + Ok(v) => { + match v { + TurnChoice::Move(d) => { + if let Some(script) = d.script().get() { + let read_lock = script.read(); + if let Some(script) = read_lock.as_ref() { + if let Some(v) = script.as_any().downcast_ref::(){ + return wasm_ok(v.get_wasm_pointer()) + } + } + } + return wasm_ok(0); + }, + _ => wasm_err::(anyhow_ext::anyhow!("Invalid turn choice"), &env) } - } - return 0; + }, + Err(e) => wasm_err::(e, &env), } - panic!("Invalid turn choice"); } diff --git a/src/script_implementations/wasm/export_registry/mod.rs b/src/script_implementations/wasm/export_registry/mod.rs index 9302096..97d89ce 100755 --- a/src/script_implementations/wasm/export_registry/mod.rs +++ b/src/script_implementations/wasm/export_registry/mod.rs @@ -1,21 +1,23 @@ use anyhow_ext::anyhow; -use anyhow_ext::Result; -use num_traits::{NumCast, PrimInt}; use std::ffi::{c_char, CStr, CString}; use std::mem::{align_of, forget}; -use std::ops::{ControlFlow, FromResidual, Try}; - -use wasmer::{FromToNativeWasmType, FunctionEnv, FunctionEnvMut, Imports, NativeWasmTypeInto, StoreMut}; +use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::EffectParameter; use crate::StringKey; +use anyhow_ext::Context; /// Dynamic data registration mod dynamic_data; /// Static data registration mod static_data; +mod wasm_object; +mod wasm_result; + +#[doc(inline)] +pub use wasm_result::*; /// Register a single function. macro_rules! register_func_with_env { @@ -94,52 +96,50 @@ fn _print(env: FunctionEnvMut, p: u32) { /// Triggers when WASM panics. #[track_caller] -fn _error(env: FunctionEnvMut, message: u32, file: u32, line: u32, position: u32) { +fn _error(env: FunctionEnvMut, message: u32) { unsafe { let mem: *const c_char = env.data().data().get_raw_pointer(message); let message_str = CStr::from_ptr(mem); - let mem: *const c_char = env.data().data().get_raw_pointer(file); - let file_str = CStr::from_ptr(mem); - - panic!( - "WASM Error: {} in file {}, line: {}:{}", - message_str.to_str().unwrap(), - file_str.to_str().unwrap(), - line, - position - ); + panic!("WASM Error: {}", message_str.to_str().unwrap()); } } /// Get a single item from an earlier passed VecExternRef fn _vec_extern_ref_get_value(env: FunctionEnvMut, reference: u32, index: u32) -> WasmResult { - let res = env - .data() - .data() - .get_extern_vec_ref_extern_ref(reference as usize, index as usize)?; - Ok(res as u32).into() + let res = try_wasm!( + env.data() + .data() + .get_extern_vec_ref_extern_ref(reference as usize, index as usize), + env + ); + wasm_ok(res as u32) } /// Gets the hash value of a StringKey. fn string_key_get_hash(env: FunctionEnvMut, string_key: ExternRef) -> WasmResult { - Ok(string_key.value_func(&env)?.hash()).into() + let value = get_value!(string_key, env); + wasm_ok(value.hash()) } /// Get a null-terminated C string from a StringKey. Note that this involves a copy into WASM /// memory, so this is relatively heavy. -fn string_key_get_str(env: FunctionEnvMut, string_key: ExternRef) -> WasmResult { - let string_key = string_key.value_func(&env)?.str(); - let wasm_string_ptr = env - .data() - .data() - .allocate_mem((string_key.len() + 1) as u32, align_of::() as u32)?; +fn string_key_get_str(env: FunctionEnvMut, string_key: ExternRef) -> (u32, u32) { + let value = get_value!(string_key, env); + let string_key = value.str(); + let wasm_string_ptr = try_wasm!( + env.data() + .data() + .allocate_mem((string_key.len() + 1) as u32, align_of::() as u32), + env + ); let mut wasm_string: Vec = unsafe { Vec::from_raw_parts(wasm_string_ptr.0, string_key.len() + 1, string_key.len() + 1) }; wasm_string.resize(string_key.len() + 1, 0); string_key.as_bytes().clone_into(&mut wasm_string); wasm_string.insert(string_key.len(), 0_u8); forget(wasm_string); - Ok(wasm_string_ptr.1).into() + println!("Returning v: {:?}", wasm_string_ptr.1); + wasm_ok(wasm_string_ptr.1) } /// Gets the type of an EffectParameter @@ -147,14 +147,13 @@ fn effect_parameter_get_type( env: FunctionEnvMut, parameter: ExternRef, ) -> WasmResult { - let v = parameter.value_func(&env)?; - Ok(match v { + let value = get_value!(parameter, env); + wasm_ok(match value { EffectParameter::Bool(_, _) => 1, EffectParameter::Int(_, _) => 2, EffectParameter::Float(_, _) => 3, EffectParameter::String(_, _) => 4, }) - .into() } /// Gets the inner bool data of an EffectParameter. Panics if it's not a bool. @@ -162,12 +161,11 @@ fn effect_parameter_as_bool( env: FunctionEnvMut, parameter: ExternRef, ) -> WasmResult { - let v = parameter.value_func(&env)?; - match v { - EffectParameter::Bool(_, b) => Ok(>::from(*b)), - _ => Err(anyhow!("Unexpected parameter type. Expected bool, got {}", v)), + let value = get_value!(parameter, env); + match value { + EffectParameter::Bool(_, b) => wasm_ok(>::from(*b)), + _ => wasm_err::(anyhow!("Unexpected parameter type. Expected bool, got {}", value), &env), } - .into() } /// Gets the inner int data of an EffectParameter. Panics if it's not an int. @@ -175,12 +173,11 @@ fn effect_parameter_as_int( env: FunctionEnvMut, parameter: ExternRef, ) -> WasmResult { - let v = parameter.value_func(&env)?; - match v { - EffectParameter::Int(_, i) => Ok(*i), - _ => Err(anyhow!("Unexpected parameter type. Expected int, got {}", v)), + let value = get_value!(parameter, env); + match value { + EffectParameter::Int(_, i) => wasm_ok(*i), + _ => wasm_err::(anyhow!("Unexpected parameter type. Expected int, got {}", value), &env), } - .into() } /// Gets the inner float data of an EffectParameter. Panics if it's not a float. @@ -188,12 +185,14 @@ fn effect_parameter_as_float( env: FunctionEnvMut, parameter: ExternRef, ) -> WasmResult { - let v = parameter.value_func(&env)?; - match v { - EffectParameter::Float(_, f) => Ok(*f), - _ => Err(anyhow!("Unexpected parameter type. Expected float, got {}", v)), + let value = get_value!(parameter, env); + match value { + EffectParameter::Float(_, f) => wasm_ok(*f), + _ => wasm_err::( + anyhow!("Unexpected parameter type. Expected float, got {}", value), + &env, + ), } - .into() } /// Gets the inner string data of an EffectParameter. Panics if it's not a string. @@ -201,58 +200,12 @@ fn effect_parameter_as_string( env: FunctionEnvMut, parameter: ExternRef, ) -> WasmResult> { - let v = parameter.value_func(&env)?; - match v { - EffectParameter::String(_, s) => Ok(ExternRef::func_new(&env, s)), - _ => Err(anyhow!("Unexpected parameter type. Expected string, got {}", v)), - } - .into() -} - -/// A result type that can be given to, or returned from WASM. -struct WasmResult(Result); - -impl WasmResult { - /// Create a new WasmResult with an OK value. - pub fn ok(value: T) -> Self { - Self(Ok(value)) - } - - /// Create a new WasmResult with an Err value. - pub fn err(value: anyhow_ext::Error) -> Self { - Self(Err(value)) - } -} - -impl From> for WasmResult { - fn from(value: Result) -> Self { - Self(value) - } -} - -impl FromResidual for WasmResult { - fn from_residual(residual: ::Residual) -> Self { - match residual { - Ok(_) => { - unimplemented!() - } - Err(e) => WasmResult(Err(e)), - } - } -} - -impl Try for WasmResult { - type Output = T; - type Residual = as Try>::Residual; - - fn from_output(output: Self::Output) -> Self { - Self(Ok(output)) - } - - fn branch(self) -> ControlFlow { - match self.0 { - Ok(v) => ControlFlow::Continue(v), - Err(e) => ControlFlow::Break(Err(e)), - } + let value = get_value!(parameter, env); + match value { + EffectParameter::Float(_, s) => wasm_ok(ExternRef::::func_new(&env, s)), + _ => wasm_err::>( + anyhow!("Unexpected parameter type. Expected string, got {}", value), + &env, + ), } } diff --git a/src/script_implementations/wasm/export_registry/static_data/form.rs b/src/script_implementations/wasm/export_registry/static_data/form.rs index 93ac351..cf21193 100644 --- a/src/script_implementations/wasm/export_registry/static_data/form.rs +++ b/src/script_implementations/wasm/export_registry/static_data/form.rs @@ -1,9 +1,10 @@ -use crate::script_implementations::wasm::export_registry::FunctionEnvMut; -use crate::script_implementations::wasm::export_registry::{register, WasmResult}; +use crate::script_implementations::wasm::export_registry::wasm_result::try_wasm; +use crate::script_implementations::wasm::export_registry::{register, wasm_ok, FunctionEnvMut, WasmResult}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::{Form, StatisticSet}; use crate::StringKey; +use anyhow_ext::Context; register! { @@ -18,11 +19,12 @@ fn form_get_name( fn form_get_types( env: FunctionEnvMut, form: ExternRef -) -> WasmResult<(u32, u32)> { +) -> WasmResult { let form = form.value_func_arc(&env).unwrap(); let vec = form.types(); - let wasm_ptr = env.data().data().copy_value_vec_to_wasm(vec)?; - Ok((wasm_ptr, vec.len() as u32)).into() + let wasm_ptr = try_wasm!(env.data().data().copy_value_vec_to_wasm(vec), env); + let r: u64 = unsafe { std::mem::transmute((wasm_ptr, vec.len() as u32)) }; + wasm_ok(r) } fn form_get_height( diff --git a/src/script_implementations/wasm/export_registry/static_data/mod.rs b/src/script_implementations/wasm/export_registry/static_data/mod.rs index 9f46317..769ba13 100755 --- a/src/script_implementations/wasm/export_registry/static_data/mod.rs +++ b/src/script_implementations/wasm/export_registry/static_data/mod.rs @@ -2,13 +2,17 @@ use std::mem::transmute; use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut}; use crate::defines::LevelInt; -use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::export_registry::wasm_result::{ + get_value, get_value_void, wasm_ok, WasmResult, +}; +use crate::script_implementations::wasm::export_registry::{register, WasmVoidResult, WasmVoidResultExtension}; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::{ ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, StaticStatisticSet, StatisticSet, TypeLibrary, }; +use anyhow_ext::Context; /// Ability data registration mod ability; @@ -62,27 +66,34 @@ register! { } } - fn statistic_set_get(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8) -> i64 { + fn statistic_set_get(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8) -> WasmResult { unsafe { - statistics_set.value_func(&env).unwrap().get_stat(transmute(stat)) as i64 + let statistics_set = get_value!(statistics_set, env); + wasm_ok(statistics_set.get_stat(transmute(stat)) as i64) } } - fn statistic_set_set(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) { + fn statistic_set_set(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) -> WasmVoidResult { unsafe { - statistics_set.value_func(&env).unwrap().set_stat(transmute(stat), value as u32) + let statistics_set = get_value_void!(statistics_set, env); + statistics_set.set_stat(transmute(stat), value as u32); + WasmVoidResult::ok() } } - fn statistic_set_increase_stat(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) { + fn statistic_set_increase_stat(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) -> WasmVoidResult { unsafe { - statistics_set.value_func(&env).unwrap().increase_stat(transmute(stat), value as u32) + let statistics_set = get_value_void!(statistics_set, env); + statistics_set.increase_stat(transmute(stat), value as u32); + WasmVoidResult::ok() } } - fn statistic_set_decrease_stat(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) { + fn statistic_set_decrease_stat(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) -> WasmVoidResult { unsafe { - statistics_set.value_func(&env).unwrap().decrease_stat(transmute(stat), value as u32) + let statistics_set = get_value_void!(statistics_set, env); + statistics_set.decrease_stat(transmute(stat), value as u32); + WasmVoidResult::ok() } } diff --git a/src/script_implementations/wasm/export_registry/wasm_object.rs b/src/script_implementations/wasm/export_registry/wasm_object.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/script_implementations/wasm/export_registry/wasm_object.rs @@ -0,0 +1 @@ + diff --git a/src/script_implementations/wasm/export_registry/wasm_result.rs b/src/script_implementations/wasm/export_registry/wasm_result.rs new file mode 100644 index 0000000..d028244 --- /dev/null +++ b/src/script_implementations/wasm/export_registry/wasm_result.rs @@ -0,0 +1,141 @@ +use crate::script_implementations::wasm::script_resolver::{WebAssemblyEnv, WebAssemblyEnvironmentData}; +use anyhow::Error; +use std::ffi::{c_char, CString}; +use std::sync::Arc; +use wasmer::{FromToNativeWasmType, FunctionEnvMut}; + +/// A result type that can be given to, or returned from WASM. +pub type WasmResult = (u32, T); + +/// A result type that can be given to, or returned from WASM, but does not contain a value. +pub type WasmVoidResult = u32; + +pub(crate) trait WasmVoidResultExtension { + fn into_result(self, env: FunctionEnvMut) -> anyhow_ext::Result<()>; + fn into_result_env(self, env: &Arc) -> anyhow_ext::Result<()>; + fn from_result(res: anyhow_ext::Result<()>, env: &FunctionEnvMut) -> Self; + fn ok() -> Self; + fn err(err: anyhow::Error, env: &FunctionEnvMut) -> Self; +} + +pub(super) fn wasm_ok(value: T) -> WasmResult +where + T: FromToNativeWasmType, + ::Native: Default, +{ + (0, value) +} + +pub(super) fn wasm_err(err: Error, env: &FunctionEnvMut) -> WasmResult +where + T: FromToNativeWasmType + Default, +{ + let s = CString::new(err.to_string()).unwrap(); + let ptr = env.data().data().copy_value_vec_to_wasm(s.as_bytes()).unwrap(); + (ptr, ::default()) +} + +impl WasmVoidResultExtension for WasmVoidResult { + fn into_result(self, env: FunctionEnvMut) -> anyhow::Result<()> { + Self::into_result_env(self, &env.data().data()) + } + + fn into_result_env(self, env: &Arc) -> anyhow::Result<()> { + if self == 0 { + Ok(()) + } else { + unsafe { + let ptr = self; + let mem: *mut c_char = env.get_raw_pointer(ptr as u32); + let string = std::ffi::CStr::from_ptr(mem); + let e = anyhow_ext::anyhow!("{}", string.to_str().unwrap()); + env.script_function_cache().dealloc_cstring(&env, ptr as u32).unwrap(); + Err(e) + } + } + } + + fn from_result(res: anyhow::Result<()>, env: &FunctionEnvMut) -> Self { + match res { + Ok(_) => 0, + Err(e) => { + let s = CString::new(e.to_string()).unwrap(); + let ptr = env.data().data().copy_value_vec_to_wasm(s.as_bytes()).unwrap(); + ptr as u32 + } + } + } + + fn ok() -> Self { + 0 + } + + fn err(err: Error, env: &FunctionEnvMut) -> Self { + let s = CString::new(err.to_string()).unwrap(); + let ptr = env.data().data().copy_value_vec_to_wasm(s.as_bytes()).unwrap(); + ptr as u32 + } +} + +macro_rules! try_wasm { + ($e:expr, $env:expr) => { + match $e.with_context(|| format!("WASM function {}", stdext::function_name!())) { + Ok(v) => v, + Err(e) => { + return crate::script_implementations::wasm::export_registry::wasm_err(e.into(), &$env); + } + } + }; +} + +macro_rules! try_wasm_void { + ($e:expr, $env:expr) => { + match $e.with_context(|| format!("WASM function {}", stdext::function_name!())) { + Ok(v) => v, + Err(e) => { + return WasmVoidResult::from_result(Err(e.into()), &$env); + } + } + }; +} + +pub(super) use try_wasm; +pub(super) use try_wasm_void; + +macro_rules! get_value { + ($e:expr, $env:expr) => { + crate::script_implementations::wasm::export_registry::try_wasm!($e.value_func(&$env), $env) + }; +} + +macro_rules! get_value_arc { + ($e:expr, $env:expr) => { + crate::script_implementations::wasm::export_registry::try_wasm!($e.value_func_arc(&$env), $env) + }; +} + +macro_rules! get_value_void { + ($e:expr, $env:expr) => { + crate::script_implementations::wasm::export_registry::try_wasm_void!($e.value_func(&$env), $env) + }; +} + +macro_rules! get_value_arc_void { + ($e:expr, $env:expr) => { + crate::script_implementations::wasm::export_registry::try_wasm_void!($e.value_func_arc(&$env), $env) + }; +} + +pub(super) use get_value; +pub(super) use get_value_arc; +pub(super) use get_value_arc_void; +pub(super) use get_value_void; + +macro_rules! get_value_call_getter { + ($e:ident.$func:ident(), $env:expr) => {{ + let _value = crate::script_implementations::wasm::export_registry::try_wasm!($e.value_func(&$env), $env); + _value.$func() + }}; +} + +pub(super) use get_value_call_getter; diff --git a/src/script_implementations/wasm/extern_ref.rs b/src/script_implementations/wasm/extern_ref.rs index 603dfbf..6b23e0b 100755 --- a/src/script_implementations/wasm/extern_ref.rs +++ b/src/script_implementations/wasm/extern_ref.rs @@ -32,6 +32,15 @@ impl Clone for ExternRef { } } +impl Default for ExternRef { + fn default() -> Self { + Self { + index: 0, + _phantom: Default::default(), + } + } +} + impl ExternRef { /// Instantiates a new ExternRef for a bit of data. If we already have made an Extern Ref for /// this data and type, we use that instead. @@ -164,6 +173,18 @@ impl Clone for VecExternRef { } } +impl Copy for VecExternRef {} + +impl Default for VecExternRef { + fn default() -> Self { + Self { + index: 0, + size: 0, + _phantom: Default::default(), + } + } +} + impl VecExternRef { /// Instantiates a new VecExternRef for a given slice. pub fn new(env: &WebAssemblyEnvironmentData, value: &Vec) -> Self { diff --git a/src/script_implementations/wasm/script.rs b/src/script_implementations/wasm/script.rs index f78c62e..2799b38 100755 --- a/src/script_implementations/wasm/script.rs +++ b/src/script_implementations/wasm/script.rs @@ -8,6 +8,7 @@ use hashbrown::HashSet; use crate::dynamic_data::{ Battle, DamageSource, DynamicLibrary, ExecutingMove, Pokemon, Script, ScriptOwnerData, TurnChoice, }; +use crate::script_implementations::wasm::export_registry::WasmVoidResultExtension; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData; use crate::script_implementations::wasm::WebAssemblyScriptCapabilities; @@ -75,7 +76,10 @@ impl WebAssemblyScript { /// Util macro to reduce function call verbosity. macro_rules! call_func { ($func:ident, $env:ident, $self:ident $(, $par_name:expr)*) => { - $func.call(&mut $env.store_mut(), $self.self_ptr $(, $par_name)*).unwrap(); + match $func.call(&mut $env.store_mut(), $self.self_ptr $(, $par_name)*) { + Ok(res) => res.into_result_env($env)?, + Err(e) => return Err(e.into()), + }; } } diff --git a/src/script_implementations/wasm/script_function_cache.rs b/src/script_implementations/wasm/script_function_cache.rs index 2f55da6..a932ad8 100755 --- a/src/script_implementations/wasm/script_function_cache.rs +++ b/src/script_implementations/wasm/script_function_cache.rs @@ -7,6 +7,7 @@ use parking_lot::RwLock; use paste::paste; use crate::dynamic_data::{Battle, DynamicLibrary, ExecutingMove, Pokemon, TurnChoice}; +use crate::script_implementations::wasm::export_registry::WasmVoidResult; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData; use crate::static_data::{EffectParameter, Item, TypeIdentifier}; @@ -26,7 +27,7 @@ macro_rules! script_function_cache { script_get_name: RwLock>>, dealloc_cstring: RwLock>>, $( - $name: RwLock>>, + $name: RwLock>>, )* } @@ -39,7 +40,7 @@ macro_rules! script_function_cache { 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 func: TypedFunction<(u32 $(,$par_type)*), WasmVoidResult> = f.typed(&env.store_ref()).unwrap(); let _ = self.$name.write().insert(func); } } @@ -49,7 +50,7 @@ macro_rules! script_function_cache { pub(crate) fn [<$name>]( &self, env: &Arc, - ) -> Option> { + ) -> Option> { { let read_lock = self.$name.read(); if let Some(f) = read_lock.as_ref() { diff --git a/src/script_implementations/wasm/script_resolver.rs b/src/script_implementations/wasm/script_resolver.rs index 13d99f2..468b20a 100755 --- a/src/script_implementations/wasm/script_resolver.rs +++ b/src/script_implementations/wasm/script_resolver.rs @@ -3,8 +3,7 @@ use std::fmt::{Debug, Formatter}; use std::mem::{align_of, forget, size_of}; use std::sync::{Arc, Weak}; -use anyhow::Result; -use anyhow_ext::{anyhow, ensure}; +use anyhow_ext::{anyhow, ensure, Context, Result}; use hashbrown::{HashMap, HashSet}; use parking_lot::lock_api::RwLockReadGuard; use parking_lot::{RawRwLock, RwLock}; @@ -54,7 +53,7 @@ struct ScriptCapabilitiesKey { impl WebAssemblyScriptResolver { /// Instantiates a new WebAssemblyScriptResolver. pub fn new() -> Box { - let compiler = wasmer::Cranelift::default(); + let compiler = wasmer::LLVM::default(); let mut features = Features::new(); features.multi_value = true; features.reference_types = true; @@ -122,7 +121,7 @@ impl WebAssemblyScriptResolver { } } - let instance = Instance::new(&mut self.store_mut(), module, &imports)?; + let instance = Instance::new(&mut self.store_mut(), module, &imports).context("Setting up the instance")?; let exports = &instance.exports; let init_fn = exports.get_extern("_init"); diff --git a/tests/common/data_getter.rs b/tests/common/data_getter.rs index 67c6f7c..cf99a99 100755 --- a/tests/common/data_getter.rs +++ b/tests/common/data_getter.rs @@ -1,4 +1,5 @@ use serde::Deserialize; +use std::sync::Arc; use pkmn_lib::dynamic_data::Battle; @@ -9,7 +10,7 @@ pub enum TestDataGetter { } impl TestDataGetter { - pub fn get(&self, battle: &Battle) -> String { + pub fn get(&self, battle: &Arc) -> String { match self { TestDataGetter::PokemonHealth { index } => battle .get_pokemon(index[0], index[1]) diff --git a/tests/common/test_case.rs b/tests/common/test_case.rs index aa04961..d3d1159 100755 --- a/tests/common/test_case.rs +++ b/tests/common/test_case.rs @@ -58,7 +58,7 @@ impl TestCase { for party in parties { battle_parties.push(BattleParty::new(party.0.clone(), party.1).unwrap()); } - let mut battle = Battle::new( + let battle = Battle::new( library, battle_parties, self.battle_setup.can_flee, @@ -67,7 +67,7 @@ impl TestCase { Some(self.battle_setup.seed), ); for action in &self.actions { - action.execute(&mut battle); + action.execute(&battle); } } } diff --git a/tests/common/test_step.rs b/tests/common/test_step.rs index 2bfc280..7eab33a 100755 --- a/tests/common/test_step.rs +++ b/tests/common/test_step.rs @@ -1,4 +1,5 @@ use serde::Deserialize; +use std::sync::Arc; use pkmn_lib::dynamic_data::Battle; use pkmn_lib::dynamic_data::{MoveChoice, PassChoice, TurnChoice}; @@ -31,11 +32,11 @@ pub enum TestStep { } impl TestStep { - pub fn execute(&self, battle: &mut Battle) { + pub fn execute(&self, battle: &Arc) { match self { TestStep::SetPokemon { place, from_party } => { let p = battle.parties()[from_party[0] as usize].get_pokemon(from_party[1] as usize); - battle.sides_mut()[place[0] as usize].set_pokemon(place[1], p).unwrap(); + battle.sides()[place[0] as usize].set_pokemon(place[1], p).unwrap(); } TestStep::SetMoveChoice { for_pokemon, @@ -72,7 +73,7 @@ impl TestStep { assert!(battle.try_set_choice(TurnChoice::Pass(PassChoice::new(p))).unwrap()); } TestStep::Assert { value, expected } => { - let v = value.get(battle); + let v = value.get(&battle); assert_eq!(&v, expected) } } diff --git a/tests/data/gen7_scripts.wasm b/tests/data/gen7_scripts.wasm index 6cb4d83..d966ca8 100755 Binary files a/tests/data/gen7_scripts.wasm and b/tests/data/gen7_scripts.wasm differ