Initial setup for results for wasm

This commit is contained in:
Deukhoofd 2023-04-23 10:10:06 +02:00
parent eb68977290
commit 0d3d5bcbe7
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
18 changed files with 511 additions and 386 deletions

View File

@ -573,6 +573,11 @@ impl ScriptContainer {
&self.script &self.script
} }
/// Whether or not the script is set.
pub fn is_any(&self) -> bool {
self.script.read().is_some()
}
/// Get the underlying script as the downcasted value. /// Get the underlying script as the downcasted value.
pub fn get_as<T: 'static>(&self) -> Result<MappedRwLockReadGuard<T>> { pub fn get_as<T: 'static>(&self) -> Result<MappedRwLockReadGuard<T>> {
let r = RwLockReadGuard::try_map(self.script.read(), |a| unsafe { let r = RwLockReadGuard::try_map(self.script.read(), |a| unsafe {

View File

@ -23,7 +23,7 @@ extern "C" fn script_resolver_drop(ptr: OwnedPtr<Box<dyn ScriptResolver>>) {
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
mod web_assembly_script_resolver { mod web_assembly_script_resolver {
use crate::dynamic_data::ScriptResolver; use crate::dynamic_data::ScriptResolver;
use crate::ffi::{ExternPointer, IdentifiablePointer}; use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult};
use crate::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver; use crate::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver;
/// Instantiates a new WebAssemblyScriptResolver. /// Instantiates a new WebAssemblyScriptResolver.
@ -41,13 +41,19 @@ mod web_assembly_script_resolver {
mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>, mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>,
arr: *const u8, arr: *const u8,
len: usize, len: usize,
) { ) -> NativeResult<()> {
unsafe { ptr.as_mut().load_wasm_from_bytes(std::slice::from_raw_parts(arr, len)) } unsafe {
ptr.as_mut()
.load_wasm_from_bytes(std::slice::from_raw_parts(arr, len))
.into()
}
} }
/// Tells the script resolver we're done loading wasm modules, and to finalize the resolver. /// Tells the script resolver we're done loading wasm modules, and to finalize the resolver.
#[no_mangle] #[no_mangle]
extern "C" fn webassembly_script_resolver_finalize(mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>) { extern "C" fn webassembly_script_resolver_finalize(
ptr.as_mut().finalize(); mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>,
) -> NativeResult<()> {
ptr.as_mut().finalize().into()
} }
} }

View File

@ -25,6 +25,7 @@
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(trait_upcasting)] #![feature(trait_upcasting)]
#![feature(lazy_cell)] #![feature(lazy_cell)]
#![feature(try_trait_v2)]
//! PkmnLib //! PkmnLib
//! PkmnLib is a full featured implementation of Pokemon. while currently focused on implementing //! PkmnLib is a full featured implementation of Pokemon. while currently focused on implementing

View File

@ -1,10 +1,3 @@
/// The WASM module handles loading dynamic scripts through WebAssembly. /// The WASM module handles loading dynamic scripts through WebAssembly.
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
// FIXME: allow these for now until we have a good result interface defined.
#[allow(clippy::unwrap_used)]
#[allow(clippy::expect_used)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::string_slice)]
#[allow(clippy::exit)]
#[allow(clippy::panic)]
pub mod wasm; pub mod wasm;

View File

@ -1,7 +1,7 @@
use crate::dynamic_data::{ use crate::dynamic_data::{
Battle, BattleParty, BattleRandom, BattleResult, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, PokemonParty, Battle, BattleParty, BattleRandom, BattleResult, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, PokemonParty,
}; };
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::StringKey; use crate::StringKey;
@ -11,141 +11,141 @@ register! {
fn battle_get_pokemon_per_side( fn battle_get_pokemon_per_side(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> u8 { ) -> WasmResult<u8> {
battle.value_func(&env).unwrap().pokemon_per_side() Ok(battle.value_func(&env)?.pokemon_per_side()).into()
} }
fn battle_get_parties( fn battle_get_parties(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> VecExternRef<BattleParty> { ) -> WasmResult<VecExternRef<BattleParty>> {
VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env).unwrap().parties()) Ok(VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env)?.parties())).into()
} }
fn battle_get_choice_queue( fn battle_get_choice_queue(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> ExternRef<ChoiceQueue> { ) -> WasmResult<ExternRef<ChoiceQueue>> {
let queue = battle.value_func(&env).unwrap().current_turn_queue().read(); let queue = battle.value_func(&env)?.current_turn_queue().read();
if let Some(queue) = queue.as_ref() { Ok(if let Some(queue) = queue.as_ref() {
ExternRef::func_new(&env, queue) ExternRef::func_new(&env, queue)
} else { } else {
ExternRef::null() ExternRef::null()
} }).into()
} }
fn battle_get_library( fn battle_get_library(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> ExternRef<dyn DynamicLibrary> { ) -> WasmResult<ExternRef<dyn DynamicLibrary>> {
ExternRef::func_new(&env, &battle.value_func_arc(&env).unwrap().library().clone()) Ok(ExternRef::func_new(&env, &battle.value_func(&env)?.library().clone())).into()
} }
fn battle_get_sides( fn battle_get_sides(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> VecExternRef<BattleSide> { ) -> WasmResult<VecExternRef<BattleSide>> {
VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env).unwrap().sides()) Ok(VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env)?.sides())).into()
} }
fn battle_get_random( fn battle_get_random(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> ExternRef<BattleRandom> { ) -> WasmResult<ExternRef<BattleRandom>> {
ExternRef::func_new(&env, battle.value_func(&env).unwrap().random()) Ok(ExternRef::func_new(&env, battle.value_func(&env)?.random())).into()
} }
fn battle_get_weather_name( fn battle_get_weather_name(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> ExternRef<StringKey> { ) -> WasmResult<ExternRef<StringKey>> {
let weather = battle.value_func(&env).unwrap().weather_name().unwrap(); let weather = battle.value_func(&env)?.weather_name()?;
if let Some(weather) = weather { Ok(if let Some(weather) = weather {
ExternRef::func_new(&env, &weather) ExternRef::func_new(&env, &weather)
} else { } else {
ExternRef::null() ExternRef::null()
} }).into()
} }
fn battle_find_party_for_pokemon( fn battle_find_party_for_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
pokemon: ExternRef<Pokemon> pokemon: ExternRef<Pokemon>
) -> ExternRef<BattleParty> { ) -> WasmResult<ExternRef<BattleParty>> {
let battle = battle.value_func(&env).unwrap(); let battle = battle.value_func(&env)?;
let pokemon = pokemon.value_func(&env).unwrap(); let pokemon = pokemon.value_func(&env)?;
for party in battle.parties() { for party in battle.parties() {
if party.party().has_pokemon(pokemon) { if party.party().has_pokemon(pokemon) {
return ExternRef::func_new(&env, party); return Ok(ExternRef::func_new(&env, party)).into();
} }
} }
ExternRef::null() Ok(ExternRef::null()).into()
} }
fn battle_get_pokemon( fn battle_get_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
side: u8, index: u8 side: u8, index: u8
) -> ExternRef<Pokemon> { ) -> WasmResult<ExternRef<Pokemon>> {
let battle = battle.value_func(&env).unwrap(); let battle = battle.value_func(&env)?;
let pokemon = battle.get_pokemon(side, index); let pokemon = battle.get_pokemon(side, index);
if let Some(pokemon) = pokemon { Ok(if let Some(pokemon) = pokemon {
ExternRef::func_new(&env, &pokemon) ExternRef::func_new(&env, &pokemon)
} else { } else {
ExternRef::null() ExternRef::null()
} }).into()
} }
fn battle_get_can_flee( fn battle_get_can_flee(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> u8 { ) -> WasmResult<u8> {
if battle.value_func(&env).unwrap().can_flee() { 1 } else { 0 } Ok(if battle.value_func(&env)?.can_flee() { 1 } else { 0 }).into()
} }
fn battle_get_number_of_sides( fn battle_get_number_of_sides(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> u8 { ) -> WasmResult<u8> {
battle.value_func(&env).unwrap().number_of_sides() Ok(battle.value_func(&env)?.number_of_sides()).into()
} }
fn battle_get_has_ended( fn battle_get_has_ended(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> u8 { ) -> WasmResult<u8> {
if battle.value_func(&env).unwrap().has_ended() { 1 } else { 0 } Ok(if battle.value_func(&env)?.has_ended() { 1 } else { 0 }).into()
} }
fn battle_get_has_ended_conclusively( fn battle_get_has_ended_conclusively(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> u8 { ) -> WasmResult<u8> {
if battle.value_func(&env).unwrap().result().is_conclusive() { 1 } else { 0 } Ok(if battle.value_func(&env)?.result().is_conclusive() { 1 } else { 0 }).into()
} }
fn battle_get_winning_side( fn battle_get_winning_side(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> u8 { ) -> WasmResult<u8> {
if let BattleResult::Conclusive(result) = battle.value_func(&env).unwrap().result() { Ok(if let BattleResult::Conclusive(result) = battle.value_func(&env)?.result() {
result result
} else { } else {
0 0
} }).into()
} }
fn battle_get_current_turn( fn battle_get_current_turn(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>, battle: ExternRef<Battle>,
) -> u32 { ) -> WasmResult<u32> {
battle.value_func(&env).unwrap().current_turn() Ok(battle.value_func(&env)?.current_turn()).into()
} }
fn battle_party_get_party( fn battle_party_get_party(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle_party: ExternRef<BattleParty>, battle_party: ExternRef<BattleParty>,
) -> ExternRef<PokemonParty> { ) -> WasmResult<ExternRef<PokemonParty>> {
ExternRef::func_new(&env, battle_party.value_func(&env).unwrap().party().as_ref()) Ok(ExternRef::func_new(&env, battle_party.value_func(&env)?.party().as_ref())).into()
} }
} }

View File

@ -1,5 +1,5 @@
use crate::dynamic_data::BattleRandom; use crate::dynamic_data::BattleRandom;
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -9,22 +9,22 @@ register! {
fn battle_random_get( fn battle_random_get(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>, battle_random: ExternRef<BattleRandom>,
) -> i32 { ) -> WasmResult<i32> {
battle_random.value_func(&env).unwrap().get().unwrap() battle_random.value_func(&env)?.get().into()
} }
fn battle_random_get_max( fn battle_random_get_max(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>, battle_random: ExternRef<BattleRandom>,
max: i32 max: i32
) -> i32 { ) -> WasmResult<i32> {
battle_random.value_func(&env).unwrap().get_max(max).unwrap() battle_random.value_func(&env)?.get_max(max).into()
} }
fn battle_random_get_between( fn battle_random_get_between(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>, battle_random: ExternRef<BattleRandom>,
min: i32, min: i32,
max: i32 max: i32
) -> i32 { ) -> WasmResult<i32> {
battle_random.value_func(&env).unwrap().get_between(min, max).unwrap() battle_random.value_func(&env)?.get_between(min, max).into()
} }
} }

View File

@ -1,9 +1,10 @@
use crate::dynamic_data::{Battle, BattleSide, Pokemon, VolatileScriptsOwner}; use crate::dynamic_data::{Battle, BattleSide, Pokemon, VolatileScriptsOwner};
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script::WebAssemblyScript;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::ScriptCategory; use crate::ScriptCategory;
use anyhow::anyhow;
use std::ffi::CStr; use std::ffi::CStr;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -11,78 +12,78 @@ register! {
fn battleside_has_fled_battle( fn battleside_has_fled_battle(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
) -> u8 { ) -> WasmResult<u8> {
u8::from(side.value_func(&env).unwrap().has_fled_battle()) Ok(u8::from(side.value_func(&env)?.has_fled_battle())).into()
} }
fn battleside_is_defeated( fn battleside_is_defeated(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
) -> u8 { ) -> WasmResult<u8> {
u8::from(side.value_func(&env).unwrap().is_defeated()) Ok(u8::from(side.value_func(&env)?.is_defeated())).into()
} }
fn battleside_get_side_index( fn battleside_get_side_index(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
) -> u8 { ) -> WasmResult<u8> {
side.value_func(&env).unwrap().index() Ok(side.value_func(&env)?.index()).into()
} }
fn battleside_get_pokemon_per_side( fn battleside_get_pokemon_per_side(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
) -> u8 { ) -> WasmResult<u8> {
side.value_func(&env).unwrap().pokemon_per_side() Ok(side.value_func(&env)?.pokemon_per_side()).into()
} }
fn battleside_get_battle( fn battleside_get_battle(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
) -> ExternRef<Battle> { ) -> WasmResult<ExternRef<Battle>> {
ExternRef::func_new(&env, side.value_func(&env).unwrap().battle().unwrap()) Ok(ExternRef::func_new(&env, side.value_func(&env)?.battle()?)).into()
} }
fn battleside_get_pokemon( fn battleside_get_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
index: u32 index: u32
) -> ExternRef<Pokemon> { ) -> WasmResult<ExternRef<Pokemon>> {
if let Some(Some(p)) = side.value_func(&env).unwrap().pokemon().get(index as usize) { Ok(if let Some(Some(p)) = side.value_func(&env)?.pokemon().get(index as usize) {
ExternRef::func_new(&env, p.as_ref()) ExternRef::func_new(&env, p.as_ref())
} else { } else {
ExternRef::null() ExternRef::null()
} }).into()
} }
fn battle_side_get_has_fled_battle( fn battle_side_get_has_fled_battle(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
) -> u8 { ) -> WasmResult<u8> {
if side.value_func(&env).unwrap().has_fled_battle() { 1 } else { 0 } Ok(if side.value_func(&env)?.has_fled_battle() { 1 } else { 0 }).into()
} }
fn battle_side_get_is_defeated( fn battle_side_get_is_defeated(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
) -> u8 { ) -> WasmResult<u8> {
if side.value_func(&env).unwrap().is_defeated() { 1 } else { 0 } Ok(if side.value_func(&env)?.is_defeated() { 1 } else { 0 }).into()
} }
fn battleside_add_volatile_by_name( fn battleside_add_volatile_by_name(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
name_ptr: u32 name_ptr: u32
) -> u32 { ) -> WasmResult<u32> {
unsafe { unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
let script = side.value_func(&env).unwrap().add_volatile_script(&c_name.as_ref().into()).unwrap(); let script = side.value_func(&env)?.add_volatile_script(&c_name.as_ref().into())?;
if let Some(script) = script { Ok(if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>().unwrap(); let script = script.get_as::<WebAssemblyScript>()?;
script.get_wasm_pointer() script.get_wasm_pointer()
} else { } else {
0 0
} }).into()
} }
} }
@ -90,22 +91,28 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
script_ptr: u32 script_ptr: u32
) -> u32 { ) -> WasmResult<u32> {
let side : &BattleSide = side.value_func(&env).unwrap(); let side : &BattleSide = side.value_func(&env)?;
unsafe { unsafe {
let env = env.data().data(); let env = env.data().data();
let name_ptr = env.script_function_cache().script_get_name(&env).unwrap().call(&mut env.store_mut(), script_ptr).unwrap(); 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 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()).unwrap(); let script = env.setup_script(script_ptr, ScriptCategory::Side, &c_name.as_ref().into(), side.into())?;
env.script_function_cache().dealloc_cstring(&env).unwrap().call(&mut env.store_mut(), name_ptr).unwrap(); env.script_function_cache().dealloc_cstring(&env, name_ptr)?;
if let Some(script) = script { Ok(if let Some(script) = script {
let script = side.add_volatile_script_with_script(script); let script = side.add_volatile_script_with_script(script)?;
let s = script.as_ref().unwrap().as_ref().unwrap().get_as::<WebAssemblyScript>().unwrap(); let s = script.as_ref().ok_or(anyhow!("Couldn't get script"))?.get_as::<WebAssemblyScript>()?;
s.get_wasm_pointer() s.get_wasm_pointer()
} else { } else {
0 0
} }).into()
} }
} }
@ -113,10 +120,10 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
name_ptr: u32 name_ptr: u32
) -> u8 { ) -> WasmResult<u8> {
unsafe { unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
u8::from(side.value_func(&env).unwrap().has_volatile_script(&c_name.as_ref().into())) Ok(u8::from(side.value_func(&env)?.has_volatile_script(&c_name.as_ref().into()))).into()
} }
} }
@ -124,16 +131,16 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
name_ptr: u32 name_ptr: u32
) -> u32 { ) -> WasmResult<u32> {
unsafe { unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
let script = side.value_func(&env).unwrap().get_volatile_script(&c_name.as_ref().into()); let script = side.value_func(&env)?.get_volatile_script(&c_name.as_ref().into());
if let Some(script) = script { Ok(if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>().unwrap(); let script = script.get_as::<WebAssemblyScript>()?;
script.get_wasm_pointer() script.get_wasm_pointer()
} else { } else {
0 0
} }).into()
} }
} }
@ -141,10 +148,10 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>, side: ExternRef<BattleSide>,
name_ptr: u32 name_ptr: u32
) { ) -> WasmResult<()> {
unsafe { unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
side.value_func(&env).unwrap().remove_volatile_script(&c_name.as_ref().into()).unwrap(); side.value_func(&env)?.remove_volatile_script(&c_name.as_ref().into()).into()
} }
} }

View File

@ -1,5 +1,5 @@
use crate::dynamic_data::{ChoiceQueue, Pokemon}; use crate::dynamic_data::{ChoiceQueue, Pokemon};
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -9,7 +9,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<ChoiceQueue>, battle_random: ExternRef<ChoiceQueue>,
pokemon: ExternRef<Pokemon> pokemon: ExternRef<Pokemon>
) -> u8 { ) -> WasmResult<u8> {
u8::from(battle_random.value_func(&env).unwrap().move_pokemon_choice_next(pokemon.value_func(&env).unwrap()).unwrap()) Ok(u8::from(battle_random.value_func(&env)?.move_pokemon_choice_next(pokemon.value_func(&env)?)?)).into()
} }
} }

View File

@ -1,5 +1,5 @@
use crate::dynamic_data::{ExecutingMove, HitData, LearnedMove, Pokemon}; use crate::dynamic_data::{ExecutingMove, HitData, LearnedMove, Pokemon};
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script::WebAssemblyScript;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
@ -10,29 +10,29 @@ register! {
fn executing_move_get_user( fn executing_move_get_user(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>, executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<Pokemon> { ) -> WasmResult<ExternRef<Pokemon>> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().user().as_ref()) Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.user().as_ref())).into()
} }
fn executing_move_get_use_move( fn executing_move_get_use_move(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>, executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<dyn MoveData> { ) -> WasmResult<ExternRef<dyn MoveData>> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().use_move()) Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.use_move())).into()
} }
fn executing_move_get_chosen_move( fn executing_move_get_chosen_move(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>, executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<LearnedMove> { ) -> WasmResult<ExternRef<LearnedMove>> {
ExternRef::func_new(&env, executing_move.value_func_arc(&env).unwrap().chosen_move().as_ref()) Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.chosen_move().as_ref())).into()
} }
fn executing_move_get_number_of_hits( fn executing_move_get_number_of_hits(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>, executing_move: ExternRef<ExecutingMove>,
) -> u8 { ) -> WasmResult<u8> {
executing_move.value_func(&env).unwrap().number_of_hits() Ok(executing_move.value_func(&env)?.number_of_hits()).into()
} }
fn executing_move_get_hit_data( fn executing_move_get_hit_data(
@ -40,24 +40,24 @@ register! {
executing_move: ExternRef<ExecutingMove>, executing_move: ExternRef<ExecutingMove>,
target: ExternRef<Pokemon>, target: ExternRef<Pokemon>,
hit: u8 hit: u8
) -> ExternRef<HitData> { ) -> WasmResult<ExternRef<HitData>> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().get_hit_data(target.value_func(&env).unwrap(), hit).unwrap()) Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.get_hit_data(target.value_func(&env)?, hit)?)).into()
} }
fn executing_move_get_number_of_targets( fn executing_move_get_number_of_targets(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>, executing_move: ExternRef<ExecutingMove>,
) -> u32 { ) -> WasmResult<u32> {
executing_move.value_func(&env).unwrap().target_count() as u32 Ok(executing_move.value_func(&env)?.target_count() as u32).into()
} }
fn executing_move_is_pokemon_target( fn executing_move_is_pokemon_target(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>, executing_move: ExternRef<ExecutingMove>,
pokemon: ExternRef<Pokemon> pokemon: ExternRef<Pokemon>
) -> u8 { ) -> WasmResult<u8> {
let pokemon = pokemon.value_func_arc(&env).unwrap(); let pokemon = pokemon.value_func_arc(&env)?;
if executing_move.value_func(&env).unwrap().is_pokemon_target(&pokemon) { 1 } else { 0 } Ok(if executing_move.value_func(&env)?.is_pokemon_target(&pokemon) { 1 } else { 0 }).into()
} }
@ -65,16 +65,14 @@ register! {
fn executing_move_get_script( fn executing_move_get_script(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>, executing_move: ExternRef<ExecutingMove>,
) -> (u32 , u32) { ) -> WasmResult<(u32 , u32)> {
let executing_move = executing_move.value_func(&env).unwrap(); let executing_move = executing_move.value_func(&env)?;
if let Some(script) = executing_move.script().get() { let script = executing_move.script();
let read_lock = script.read(); if script.is_any() {
if let Some(script) = read_lock.as_ref() { let s = script.get_as::<WebAssemblyScript>()?.get_wasm_pointer();
let s = script.as_any().downcast_ref::<WebAssemblyScript>().unwrap().get_wasm_pointer(); return Ok((s, s + 4)).into()
return (s, s + 4)
} }
} Ok((0, 0)).into()
(0, 0)
} }
} }

View File

@ -2,13 +2,14 @@ use std::mem::transmute;
use crate::defines::LevelInt; use crate::defines::LevelInt;
use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner}; use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner};
use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::export_registry::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script::WebAssemblyScript;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{Ability, ClampedStatisticSet, Form, Nature, Species}; use crate::static_data::{Ability, ClampedStatisticSet, Form, Nature, Species};
use crate::static_data::{Item, StatisticSet}; use crate::static_data::{Item, StatisticSet};
use crate::ScriptCategory; use crate::{ScriptCategory, VecExt};
use anyhow::anyhow;
use std::ffi::{c_char, CStr, CString}; use std::ffi::{c_char, CStr, CString};
use wasmer::FunctionEnvMut; use wasmer::FunctionEnvMut;
@ -16,88 +17,89 @@ register! {
fn pokemon_get_library( fn pokemon_get_library(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn DynamicLibrary> { ) -> WasmResult<ExternRef<dyn DynamicLibrary>> {
let lib = pokemon.value_func(&env).unwrap().library().clone(); let lib = pokemon.value_func(&env)?.library().clone();
ExternRef::func_new(&env, &lib) Ok(ExternRef::func_new(&env, &lib)).into()
} }
fn pokemon_get_boosted_stats( fn pokemon_get_boosted_stats(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<StatisticSet<u32>> { ) -> WasmResult<ExternRef<StatisticSet<u32>>> {
let statistic_set = pokemon.value_func(&env).unwrap().boosted_stats(); let statistic_set = pokemon.value_func(&env)?.boosted_stats();
ExternRef::func_new(&env, statistic_set) Ok(ExternRef::func_new(&env, statistic_set)).into()
} }
fn pokemon_get_flat_stats( fn pokemon_get_flat_stats(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<StatisticSet<u32>> { ) -> WasmResult<ExternRef<StatisticSet<u32>>> {
let statistic_set = pokemon.value_func(&env).unwrap().flat_stats(); let statistic_set = pokemon.value_func(&env)?.flat_stats();
ExternRef::func_new(&env, statistic_set) Ok(ExternRef::func_new(&env, statistic_set)).into()
} }
fn pokemon_get_stat_boosts( fn pokemon_get_stat_boosts(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<i8, -6, 6>> { ) -> WasmResult<ExternRef<ClampedStatisticSet<i8, -6, 6>>> {
let statistic_set = pokemon.value_func(&env).unwrap().stat_boosts(); let statistic_set = pokemon.value_func(&env)?.stat_boosts();
ExternRef::func_new(&env, statistic_set) Ok(ExternRef::func_new(&env, statistic_set)).into()
} }
fn pokemon_get_individual_values( fn pokemon_get_individual_values(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<u8, 0, 31>> { ) -> WasmResult<ExternRef<ClampedStatisticSet<u8, 0, 31>>> {
let statistic_set = pokemon.value_func(&env).unwrap().individual_values(); let statistic_set = pokemon.value_func(&env)?.individual_values();
ExternRef::func_new(&env, statistic_set) Ok(ExternRef::func_new(&env, statistic_set)).into()
} }
fn pokemon_get_effort_values( fn pokemon_get_effort_values(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<u8, 0, 252>> { ) -> WasmResult<ExternRef<ClampedStatisticSet<u8, 0, 252>>> {
let statistic_set = pokemon.value_func(&env).unwrap().effort_values(); let statistic_set = pokemon.value_func(&env)?.effort_values();
ExternRef::func_new(&env, statistic_set) Ok(ExternRef::func_new(&env, statistic_set)).into()
} }
fn pokemon_get_species( fn pokemon_get_species(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Species> { ) -> WasmResult<ExternRef<dyn Species>> {
let species = pokemon.value_func(&env).unwrap().species(); let species = pokemon.value_func(&env)?.species();
ExternRef::func_new(&env, &species) Ok(ExternRef::func_new(&env, &species)).into()
} }
fn pokemon_get_weight( fn pokemon_get_weight(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> f32 { ) -> WasmResult<f32> {
pokemon.value_func(&env).unwrap().weight() Ok(pokemon.value_func(&env)?.weight()).into()
} }
fn pokemon_set_weight( fn pokemon_set_weight(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
weight: f32, weight: f32,
) { ) -> WasmResult<()> {
pokemon.value_func(&env).unwrap().set_weight(weight) pokemon.value_func(&env)?.set_weight(weight);
Ok(()).into()
} }
fn pokemon_get_height( fn pokemon_get_height(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> f32 { ) -> WasmResult<f32> {
pokemon.value_func(&env).unwrap().height() Ok(pokemon.value_func(&env)?.height()).into()
} }
fn pokemon_get_gender( fn pokemon_get_gender(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u8 { ) -> WasmResult<u8> {
unsafe { unsafe {
transmute(pokemon.value_func(&env).unwrap().gender()) Ok(transmute(pokemon.value_func(&env)?.gender())).into()
} }
} }
@ -106,9 +108,10 @@ register! {
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
damage: u32, damage: u32,
source: u8 source: u8
) { ) -> WasmResult<()> {
unsafe{ unsafe{
pokemon.value_func(&env).unwrap().damage(damage, transmute(source)).unwrap(); pokemon.value_func(&env)?.damage(damage, transmute(source))?;
WasmResult::ok(())
} }
} }
@ -116,15 +119,15 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
index: u32 index: u32
) -> ExternRef<LearnedMove> { ) -> WasmResult<ExternRef<LearnedMove>> {
let read_lock = pokemon.value_func(&env).unwrap().learned_moves().read(); let read_lock = pokemon.value_func(&env)?.learned_moves().read();
let mv = read_lock.get(index as usize); let mv = read_lock.get(index as usize);
if let Some(Some(mv)) = mv { Ok(if let Some(Some(mv)) = mv {
ExternRef::func_new(&env, mv) ExternRef::func_new(&env, mv)
} }
else{ else{
ExternRef::null() ExternRef::null()
} }).into()
} }
fn pokemon_change_stat_boost( fn pokemon_change_stat_boost(
@ -133,65 +136,65 @@ register! {
stat: u8, stat: u8,
amount: i8, amount: i8,
self_inflicted: u8 self_inflicted: u8
) -> u8 { ) -> WasmResult<u8> {
unsafe{ unsafe{
u8::from(pokemon.value_func(&env).unwrap().change_stat_boost(transmute(stat), amount, self_inflicted == 1).unwrap()) Ok(u8::from(pokemon.value_func(&env)?.change_stat_boost(transmute(stat), amount, self_inflicted == 1)?)).into()
} }
} }
fn pokemon_get_battle( fn pokemon_get_battle(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<Battle> { ) -> WasmResult<ExternRef<Battle>> {
if let Some(battle) = pokemon.value_func(&env).unwrap().get_battle() { Ok(if let Some(battle) = pokemon.value_func(&env)?.get_battle() {
ExternRef::func_new(&env, battle) ExternRef::func_new(&env, battle)
} else { } else {
ExternRef::null() ExternRef::null()
} }).into()
} }
fn pokemon_get_battle_index( fn pokemon_get_battle_index(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u8 { ) -> WasmResult<u8> {
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_index() { Ok(if let Some(i) = pokemon.value_func(&env)?.get_battle_index() {
i i
} else { } else {
255 255
} }).into()
} }
fn pokemon_get_battle_side_index( fn pokemon_get_battle_side_index(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u8 { ) -> WasmResult<u8> {
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_side_index() { Ok(if let Some(i) = pokemon.value_func(&env)?.get_battle_side_index() {
i i
} else { } else {
255 255
} }).into()
} }
fn pokemon_get_held_item( fn pokemon_get_held_item(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Item> { ) -> WasmResult<ExternRef<dyn Item>> {
let read_lock = pokemon.value_func(&env).unwrap().held_item().read(); let read_lock = pokemon.value_func(&env)?.held_item().read();
if let Some(item) = read_lock.as_ref() { Ok(if let Some(item) = read_lock.as_ref() {
ExternRef::func_new(&env, item.as_ref()) ExternRef::func_new(&env, item.as_ref())
} else { } else {
ExternRef::null() ExternRef::null()
} }).into()
} }
fn pokemon_has_held_item( fn pokemon_has_held_item(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
name: u32 name: u32
) -> u8 { ) -> WasmResult<u8> {
let name : *mut c_char = env.data().data().get_raw_pointer(name); let name : *mut c_char = env.data().data().get_raw_pointer(name);
let name = unsafe { CStr::from_ptr(name) }; let name = unsafe { CStr::from_ptr(name) };
u8::from(pokemon.value_func(&env).unwrap().has_held_item(&name.into())) Ok(u8::from(pokemon.value_func(&env)?.has_held_item(&name.into()))).into()
} }
fn pokemon_heal( fn pokemon_heal(
@ -199,51 +202,52 @@ register! {
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
amount: u32, amount: u32,
allow_revive: u8 allow_revive: u8
) -> u8 { ) -> WasmResult<u8> {
u8::from(pokemon.value_func(&env).unwrap().heal(amount, allow_revive == 1)) Ok(u8::from(pokemon.value_func(&env)?.heal(amount, allow_revive == 1))).into()
} }
fn pokemon_clear_status( fn pokemon_clear_status(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) { ) -> WasmResult<()> {
pokemon.value_func(&env).unwrap().clear_status() pokemon.value_func(&env)?.clear_status();
WasmResult::ok(())
} }
fn pokemon_get_active_ability( fn pokemon_get_active_ability(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Ability> { ) -> WasmResult<ExternRef<dyn Ability>> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().active_ability()) Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.active_ability())).into()
} }
fn pokemon_get_real_ability( fn pokemon_get_real_ability(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> (u8, u8) { ) -> WasmResult<(u8, u8)> {
let index = &pokemon.value_func(&env).unwrap().real_ability(); let index = &pokemon.value_func(&env)?.real_ability();
(if index.hidden { 1 } else { 0 }, index.index) WasmResult::ok((if index.hidden { 1 } else { 0 }, index.index))
} }
fn pokemon_get_is_ability_overriden( fn pokemon_get_is_ability_overriden(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u8 { ) -> WasmResult<u8> {
if pokemon.value_func(&env).unwrap().is_ability_overriden() { 1 } else { 0 } Ok(if pokemon.value_func(&env)?.is_ability_overriden() { 1 } else { 0 }).into()
} }
fn pokemon_get_allowed_experience_gain( fn pokemon_get_allowed_experience_gain(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u8 { ) -> WasmResult<u8> {
if pokemon.value_func(&env).unwrap().allowed_experience_gain() { 1 } else { 0 } Ok(if pokemon.value_func(&env)?.allowed_experience_gain() { 1 } else { 0 }).into()
} }
fn pokemon_get_is_usable( fn pokemon_get_is_usable(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u8 { ) -> WasmResult<u8> {
if pokemon.value_func(&env).unwrap().is_usable() { 1 } else { 0 } Ok(if pokemon.value_func(&env)?.is_usable() { 1 } else { 0 }).into()
} }
@ -251,56 +255,56 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
item: ExternRef<dyn Item> item: ExternRef<dyn Item>
) -> ExternRef<dyn Item> { ) -> WasmResult<ExternRef<dyn Item>> {
let item = item.value_func_arc(&env).unwrap(); let item = item.value_func_arc(&env)?;
let old_item = pokemon.value_func(&env).unwrap().set_held_item(&item); let old_item = pokemon.value_func(&env)?.set_held_item(&item);
if let Some(old_item) = old_item { Ok(if let Some(old_item) = old_item {
ExternRef::func_new(&env, &old_item) ExternRef::func_new(&env, &old_item)
} else { } else {
ExternRef::null() ExternRef::null()
} }).into()
} }
fn pokemon_remove_held_item( fn pokemon_remove_held_item(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Item> { ) -> WasmResult<ExternRef<dyn Item>> {
let old_item = pokemon.value_func(&env).unwrap().remove_held_item(); let old_item = pokemon.value_func(&env)?.remove_held_item();
if let Some(old_item) = old_item { Ok(if let Some(old_item) = old_item {
ExternRef::func_new(&env, &old_item) ExternRef::func_new(&env, &old_item)
} else { } else {
ExternRef::null() ExternRef::null()
} }).into()
} }
fn pokemon_consume_held_item( fn pokemon_consume_held_item(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u8 { ) -> WasmResult<u8> {
if pokemon.value_func(&env).unwrap().consume_held_item().unwrap() { 1 } else { 0 } Ok(if pokemon.value_func(&env)?.consume_held_item()? { 1 } else { 0 }).into()
} }
fn pokemon_get_types_length( fn pokemon_get_types_length(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon> pokemon: ExternRef<Pokemon>
) -> u32 { ) -> WasmResult<u32> {
pokemon.value_func(&env).unwrap().types().len() as u32 Ok(pokemon.value_func(&env)?.types().len() as u32).into()
} }
fn pokemon_get_type( fn pokemon_get_type(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
index: u32 index: u32
) -> u8 { ) -> WasmResult<u8> {
(*pokemon.value_func(&env).unwrap().types().get(index as usize).unwrap()).into() Ok((*pokemon.value_func(&env)?.types().get_res(index as usize)?).into()).into()
} }
fn pokemon_has_type( fn pokemon_has_type(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
t: u8 t: u8
) -> u8 { ) -> WasmResult<u8> {
if pokemon.value_func(&env).unwrap().types().contains(&t.into()) { 1 } else { 0 } Ok(if pokemon.value_func(&env)?.types().contains(&t.into()) { 1 } else { 0 }).into()
} }
fn pokemon_change_species( fn pokemon_change_species(
@ -308,97 +312,102 @@ register! {
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
species: ExternRef<dyn Species>, species: ExternRef<dyn Species>,
form: ExternRef<dyn Form>, form: ExternRef<dyn Form>,
) { ) -> WasmResult<()> {
pokemon.value_func(&env).unwrap().change_species( pokemon.value_func(&env)?.change_species(
species.value_func_arc(&env).unwrap(), species.value_func_arc(&env)?,
form.value_func_arc(&env).unwrap(), form.value_func_arc(&env)?,
).unwrap(); )?;
WasmResult::ok(())
} }
fn pokemon_change_form( fn pokemon_change_form(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
form: ExternRef<dyn Form>, form: ExternRef<dyn Form>,
) { ) -> WasmResult<()> {
pokemon.value_func(&env).unwrap().change_form( pokemon.value_func(&env)?.change_form(
&form.value_func_arc(&env).unwrap(), &form.value_func_arc(&env)?,
).unwrap(); )?;
WasmResult::ok(())
} }
fn pokemon_get_current_health( fn pokemon_get_current_health(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u32 { ) -> WasmResult<u32> {
pokemon.value_func(&env).unwrap().current_health() Ok(pokemon.value_func(&env)?.current_health()).into()
} }
fn pokemon_get_nature( fn pokemon_get_nature(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Nature> { ) -> WasmResult<ExternRef<dyn Nature>> {
ExternRef::func_new(&env, pokemon.value_func(&env).unwrap().nature()) Ok(ExternRef::func_new(&env, pokemon.value_func(&env)?.nature())).into()
} }
fn pokemon_get_form( fn pokemon_get_form(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Form> { ) -> WasmResult<ExternRef<dyn Form>> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().form()) Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.form())).into()
} }
fn pokemon_get_display_species( fn pokemon_get_display_species(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Species> { ) -> WasmResult<ExternRef<dyn Species>> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().display_species()) Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.display_species())).into()
} }
fn pokemon_get_display_form( fn pokemon_get_display_form(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Form> { ) -> WasmResult<ExternRef<dyn Form>> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().display_form()) Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.display_form())).into()
} }
fn pokemon_get_level( fn pokemon_get_level(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> LevelInt { ) -> WasmResult<LevelInt> {
pokemon.value_func(&env).unwrap().level() Ok(pokemon.value_func(&env)?.level()).into()
} }
fn pokemon_get_experience( fn pokemon_get_experience(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u32 { ) -> WasmResult<u32> {
pokemon.value_func(&env).unwrap().experience() Ok(pokemon.value_func(&env)?.experience()).into()
} }
fn pokemon_get_unique_identifier( fn pokemon_get_unique_identifier(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u32 { ) -> WasmResult<u32> {
pokemon.value_func(&env).unwrap().unique_identifier() Ok(pokemon.value_func(&env)?.unique_identifier()).into()
} }
fn pokemon_get_coloring( fn pokemon_get_coloring(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u8 { ) -> WasmResult<u8> {
pokemon.value_func(&env).unwrap().coloring() Ok(pokemon.value_func(&env)?.coloring()).into()
} }
fn pokemon_get_nickname( fn pokemon_get_nickname(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u32 { ) -> WasmResult<u32> {
let pokemon = pokemon.value_func(&env).unwrap(); let pokemon = pokemon.value_func(&env)?;
let nickname = pokemon.nickname(); let nickname = pokemon.nickname();
if let Some(nickname) = nickname { if let Some(nickname) = nickname {
let nickname: CString = CString::new(nickname.as_str()).unwrap(); let nickname: CString = match CString::new(nickname.as_str()) {
env.data().data().copy_value_vec_to_wasm(nickname.as_bytes()) Ok(nickname) => nickname,
Err(e) => return WasmResult::err(e.into()),
};
env.data().data().copy_value_vec_to_wasm(nickname.as_bytes()).into()
} else { } else {
0 Ok(0).into()
} }
} }
@ -408,15 +417,15 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
name_ptr: u32 name_ptr: u32
) -> u32 { ) -> WasmResult<u32> {
unsafe { unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
let script = pokemon.value_func(&env).unwrap().add_volatile_script(&c_name.as_ref().into()).unwrap(); let script = pokemon.value_func(&env)?.add_volatile_script(&c_name.as_ref().into())?;
if let Some(script) = script { if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>().unwrap(); let script = script.get_as::<WebAssemblyScript>()?;
script.get_wasm_pointer() Ok(script.get_wasm_pointer()).into()
} else { } else {
0 Ok(0).into()
} }
} }
} }
@ -425,21 +434,24 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
script_ptr: u32 script_ptr: u32
) -> u32 { ) -> WasmResult<u32> {
let pokemon : &Pokemon = pokemon.value_func(&env).unwrap(); let pokemon : &Pokemon = pokemon.value_func(&env)?;
unsafe{ unsafe{
let env = env.data().data(); let env = env.data().data();
let name_ptr = env.script_function_cache().script_get_name(&env).unwrap().call(&mut env.store_mut(), script_ptr).unwrap(); let name_ptr = match env.script_function_cache().script_get_name(&env)?.call(&mut env.store_mut(), script_ptr){
Ok(name_ptr) => name_ptr,
Err(e) => return WasmResult::err(e.into())
};
let c_name: &CStr = CStr::from_ptr(env.get_raw_pointer(name_ptr)); 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()).unwrap(); let script = env.setup_script(script_ptr, ScriptCategory::Pokemon, &c_name.as_ref().into(), pokemon.into())?;
env.script_function_cache().dealloc_cstring(&env).unwrap().call(&mut env.store_mut(), name_ptr).unwrap(); env.script_function_cache().dealloc_cstring(&env, name_ptr)?;
if let Some(script) = script { if let Some(script) = script {
let script = pokemon.add_volatile_script_with_script(script); let script = pokemon.add_volatile_script_with_script(script)?;
let s = script.as_ref().unwrap().as_ref().unwrap().get_as::<WebAssemblyScript>().unwrap(); let s = script.as_ref().ok_or(anyhow!("Unable to get script"))?.get_as::<WebAssemblyScript>()?;
s.get_wasm_pointer() WasmResult::ok(s.get_wasm_pointer())
} else { } else {
0 WasmResult::ok(0)
} }
} }
} }
@ -448,10 +460,10 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
name_ptr: u32 name_ptr: u32
) -> u8 { ) -> WasmResult<u8> {
unsafe { unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
u8::from(pokemon.value_func(&env).unwrap().has_volatile_script(&c_name.as_ref().into())) Ok(u8::from(pokemon.value_func(&env)?.has_volatile_script(&c_name.as_ref().into()))).into()
} }
} }
@ -459,16 +471,16 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
name_ptr: u32 name_ptr: u32
) -> u32 { ) -> WasmResult<u32> {
unsafe { unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
let script = pokemon.value_func(&env).unwrap().get_volatile_script(&c_name.as_ref().into()); let script = pokemon.value_func(&env)?.get_volatile_script(&c_name.as_ref().into());
if let Some(script) = script { Ok(if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>().unwrap(); let script = script.get_as::<WebAssemblyScript>()?;
script.get_wasm_pointer() script.get_wasm_pointer()
} else { } else {
0 0
} }).into()
} }
} }
@ -476,25 +488,24 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
name_ptr: u32 name_ptr: u32
) { ) -> WasmResult<()> {
unsafe { unsafe {
let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr)); let c_name = CStr::from_ptr(env.data().data().get_raw_pointer(name_ptr));
pokemon.value_func(&env).unwrap().remove_volatile_script(&c_name.as_ref().into()).unwrap(); pokemon.value_func(&env)?.remove_volatile_script(&c_name.as_ref().into())?;
WasmResult::ok(())
} }
} }
fn pokemon_get_ability_script( fn pokemon_get_ability_script(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>, pokemon: ExternRef<Pokemon>,
) -> u32 { ) -> WasmResult<u32> {
let pokemon = pokemon.value_func(&env).unwrap(); let pokemon = pokemon.value_func(&env)?;
if let Some(script) = pokemon.ability_script().get() { let script = pokemon.ability_script();
let read_lock = script.read(); if script.is_any() {
if let Some(script) = read_lock.as_ref() { return Ok(script.get_as::<WebAssemblyScript>()?.get_wasm_pointer()).into();
return script.as_any().downcast_ref::<WebAssemblyScript>().unwrap().get_wasm_pointer()
} }
} WasmResult::ok(0)
0
} }
} }

View File

@ -1,7 +1,11 @@
use anyhow_ext::anyhow;
use anyhow_ext::Result;
use num_traits::{NumCast, PrimInt};
use std::ffi::{c_char, CStr, CString}; use std::ffi::{c_char, CStr, CString};
use std::mem::{align_of, forget}; use std::mem::{align_of, forget};
use std::ops::{ControlFlow, FromResidual, Try};
use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut}; use wasmer::{FromToNativeWasmType, FunctionEnv, FunctionEnvMut, Imports, NativeWasmTypeInto, StoreMut};
use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::extern_ref::ExternRef;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
@ -108,80 +112,147 @@ fn _error(env: FunctionEnvMut<WebAssemblyEnv>, message: u32, file: u32, line: u3
} }
/// Get a single item from an earlier passed VecExternRef /// Get a single item from an earlier passed VecExternRef
fn _vec_extern_ref_get_value(env: FunctionEnvMut<WebAssemblyEnv>, reference: u32, index: u32) -> u32 { fn _vec_extern_ref_get_value(env: FunctionEnvMut<WebAssemblyEnv>, reference: u32, index: u32) -> WasmResult<u32> {
env.data() let res = env
.data() .data()
.get_extern_vec_ref_extern_ref(reference as usize, index as usize) as u32 .data()
.get_extern_vec_ref_extern_ref(reference as usize, index as usize)?;
Ok(res as u32).into()
} }
/// Gets the hash value of a StringKey. /// Gets the hash value of a StringKey.
fn string_key_get_hash(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 { fn string_key_get_hash(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> WasmResult<u32> {
string_key.value_func(&env).unwrap().hash() Ok(string_key.value_func(&env)?.hash()).into()
} }
/// Get a null-terminated C string from a StringKey. Note that this involves a copy into WASM /// Get a null-terminated C string from a StringKey. Note that this involves a copy into WASM
/// memory, so this is relatively heavy. /// memory, so this is relatively heavy.
fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 { fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> WasmResult<u32> {
let string_key = string_key.value_func(&env).unwrap().str(); let string_key = string_key.value_func(&env)?.str();
let wasm_string_ptr = env let wasm_string_ptr = env
.data() .data()
.data() .data()
.allocate_mem((string_key.len() + 1) as u32, align_of::<CString>() as u32); .allocate_mem((string_key.len() + 1) as u32, align_of::<CString>() as u32)?;
let mut wasm_string: Vec<u8> = let mut wasm_string: Vec<u8> =
unsafe { Vec::from_raw_parts(wasm_string_ptr.0, string_key.len() + 1, string_key.len() + 1) }; 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); wasm_string.resize(string_key.len() + 1, 0);
string_key.as_bytes().clone_into(&mut wasm_string); string_key.as_bytes().clone_into(&mut wasm_string);
wasm_string.insert(string_key.len(), 0_u8); wasm_string.insert(string_key.len(), 0_u8);
forget(wasm_string); forget(wasm_string);
wasm_string_ptr.1 Ok(wasm_string_ptr.1).into()
} }
/// Gets the type of an EffectParameter /// Gets the type of an EffectParameter
fn effect_parameter_get_type(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 { fn effect_parameter_get_type(
let v = parameter.value_func(&env).unwrap(); env: FunctionEnvMut<WebAssemblyEnv>,
match v { parameter: ExternRef<EffectParameter>,
) -> WasmResult<u8> {
let v = parameter.value_func(&env)?;
Ok(match v {
EffectParameter::Bool(_, _) => 1, EffectParameter::Bool(_, _) => 1,
EffectParameter::Int(_, _) => 2, EffectParameter::Int(_, _) => 2,
EffectParameter::Float(_, _) => 3, EffectParameter::Float(_, _) => 3,
EffectParameter::String(_, _) => 4, EffectParameter::String(_, _) => 4,
} })
.into()
} }
/// Gets the inner bool data of an EffectParameter. Panics if it's not a bool. /// Gets the inner bool data of an EffectParameter. Panics if it's not a bool.
fn effect_parameter_as_bool(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 { fn effect_parameter_as_bool(
let v = parameter.value_func(&env).unwrap(); env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>,
) -> WasmResult<u8> {
let v = parameter.value_func(&env)?;
match v { match v {
EffectParameter::Bool(_, b) => u8::from(*b), EffectParameter::Bool(_, b) => Ok(<u8 as From<bool>>::from(*b)),
_ => panic!("Unexpected parameter type!"), _ => Err(anyhow!("Unexpected parameter type. Expected bool, got {}", v)),
} }
.into()
} }
/// Gets the inner int data of an EffectParameter. Panics if it's not an int. /// Gets the inner int data of an EffectParameter. Panics if it's not an int.
fn effect_parameter_as_int(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> i64 { fn effect_parameter_as_int(
let v = parameter.value_func(&env).unwrap(); env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>,
) -> WasmResult<i64> {
let v = parameter.value_func(&env)?;
match v { match v {
EffectParameter::Int(_, i) => *i, EffectParameter::Int(_, i) => Ok(*i),
_ => panic!("Unexpected parameter type!"), _ => Err(anyhow!("Unexpected parameter type. Expected int, got {}", v)),
} }
.into()
} }
/// Gets the inner float data of an EffectParameter. Panics if it's not a float. /// Gets the inner float data of an EffectParameter. Panics if it's not a float.
fn effect_parameter_as_float(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> f32 { fn effect_parameter_as_float(
let v = parameter.value_func(&env).unwrap(); env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>,
) -> WasmResult<f32> {
let v = parameter.value_func(&env)?;
match v { match v {
EffectParameter::Float(_, f) => *f, EffectParameter::Float(_, f) => Ok(*f),
_ => panic!("Unexpected parameter type!"), _ => Err(anyhow!("Unexpected parameter type. Expected float, got {}", v)),
} }
.into()
} }
/// Gets the inner string data of an EffectParameter. Panics if it's not a string. /// Gets the inner string data of an EffectParameter. Panics if it's not a string.
fn effect_parameter_as_string( fn effect_parameter_as_string(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>, parameter: ExternRef<EffectParameter>,
) -> ExternRef<StringKey> { ) -> WasmResult<ExternRef<StringKey>> {
let v = parameter.value_func(&env).unwrap(); let v = parameter.value_func(&env)?;
match v { match v {
EffectParameter::String(_, s) => ExternRef::func_new(&env, s), EffectParameter::String(_, s) => Ok(ExternRef::func_new(&env, s)),
_ => panic!("Unexpected parameter type!"), _ => Err(anyhow!("Unexpected parameter type. Expected string, got {}", v)),
}
.into()
}
/// A result type that can be given to, or returned from WASM.
struct WasmResult<T>(Result<T>);
impl<T> WasmResult<T> {
/// 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<T> From<Result<T>> for WasmResult<T> {
fn from(value: Result<T>) -> Self {
Self(value)
}
}
impl<T> FromResidual for WasmResult<T> {
fn from_residual(residual: <Self as Try>::Residual) -> Self {
match residual {
Ok(_) => {
unimplemented!()
}
Err(e) => WasmResult(Err(e)),
}
}
}
impl<T> Try for WasmResult<T> {
type Output = T;
type Residual = <Result<T> as Try>::Residual;
fn from_output(output: Self::Output) -> Self {
Self(Ok(output))
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self.0 {
Ok(v) => ControlFlow::Continue(v),
Err(e) => ControlFlow::Break(Err(e)),
}
} }
} }

View File

@ -1,5 +1,5 @@
use crate::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::export_registry::FunctionEnvMut; use crate::script_implementations::wasm::export_registry::FunctionEnvMut;
use crate::script_implementations::wasm::export_registry::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{Form, StatisticSet}; use crate::static_data::{Form, StatisticSet};
@ -18,11 +18,11 @@ fn form_get_name(
fn form_get_types( fn form_get_types(
env: FunctionEnvMut<WebAssemblyEnv>, env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form> form: ExternRef<dyn Form>
) -> (u32, u32) { ) -> WasmResult<(u32, u32)> {
let form = form.value_func_arc(&env).unwrap(); let form = form.value_func_arc(&env).unwrap();
let vec = form.types(); let vec = form.types();
let wasm_ptr = env.data().data().copy_value_vec_to_wasm(vec); let wasm_ptr = env.data().data().copy_value_vec_to_wasm(vec)?;
(wasm_ptr, vec.len() as u32) Ok((wasm_ptr, vec.len() as u32)).into()
} }
fn form_get_height( fn form_get_height(

View File

@ -1,4 +1,5 @@
use crate::ValueIdentifiable; use crate::{PkmnError, ValueIdentifiable};
use anyhow_ext::Result;
use std::any::Any; use std::any::Any;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::transmute; use std::mem::transmute;
@ -68,25 +69,26 @@ impl<T: ValueIdentifiable + ?Sized> ExternRef<T> {
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic. /// value when it was passed before. If these types do not match, this will panic.
pub fn value_func<'a>(&self, env: &'a FunctionEnvMut<WebAssemblyEnv>) -> Option<&'a T> pub fn value_func<'a>(&self, env: &'a FunctionEnvMut<WebAssemblyEnv>) -> Result<&'a T>
where where
T: Sized + 'static, T: Sized + 'static,
{ {
self.value(&env.data().data()) self.value(&env.data().data())?.ok_or(PkmnError::NullReference.into())
} }
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic. /// value when it was passed before. If these types do not match, this will panic.
pub fn value_func_arc(&self, env: &FunctionEnvMut<WebAssemblyEnv>) -> Option<Arc<T>> pub fn value_func_arc(&self, env: &FunctionEnvMut<WebAssemblyEnv>) -> Result<Arc<T>>
where where
T: 'static, T: 'static,
{ {
self.value_arc(&env.data().data()) self.value_arc(&env.data().data())?
.ok_or(PkmnError::NullReference.into())
} }
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic. /// value when it was passed before. If these types do not match, this will panic.
pub fn value_func_box(&self, env: &FunctionEnvMut<WebAssemblyEnv>) -> Option<&Box<T>> pub fn value_func_box(&self, env: &FunctionEnvMut<WebAssemblyEnv>) -> Result<&Box<T>>
where where
T: 'static, T: 'static,
{ {
@ -95,31 +97,34 @@ impl<T: ValueIdentifiable + ?Sized> ExternRef<T> {
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic. /// value when it was passed before. If these types do not match, this will panic.
pub fn value<'a>(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Option<&'a T> pub fn value<'a>(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Result<Option<&'a T>>
where where
T: Sized + 'static, T: Sized + 'static,
{ {
env.get_extern_ref_value::<T>(self.index).downcast_ref::<T>() Ok(env.get_extern_ref_value::<T>(self.index)?.downcast_ref::<T>())
} }
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic. /// value when it was passed before. If these types do not match, this will panic.
pub fn value_arc(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Option<Arc<T>> pub fn value_arc(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Result<Option<Arc<T>>>
where where
T: 'static, T: 'static,
{ {
env.get_extern_ref_value::<T>(self.index) Ok(env
.get_extern_ref_value::<T>(self.index)?
.downcast_ref::<Arc<T>>() .downcast_ref::<Arc<T>>()
.cloned() .cloned())
} }
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the /// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
/// value when it was passed before. If these types do not match, this will panic. /// value when it was passed before. If these types do not match, this will panic.
pub fn value_box(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Option<&Box<T>> pub fn value_box(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Result<&Box<T>>
where where
T: 'static, T: 'static,
{ {
env.get_extern_ref_value::<T>(self.index).downcast_ref::<Box<T>>() env.get_extern_ref_value::<T>(self.index)?
.downcast_ref::<Box<T>>()
.ok_or(PkmnError::NullReference.into())
} }
} }

View File

@ -1,4 +1,4 @@
use anyhow_ext::Result; use anyhow_ext::{anyhow, Result};
use std::any::Any; use std::any::Any;
use std::sync::atomic::{AtomicBool, AtomicUsize}; use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::Arc; use std::sync::Arc;
@ -189,7 +189,11 @@ impl Script for WebAssemblyScript {
let move_ref = ex_ref!(env, move_name); let move_ref = ex_ref!(env, move_name);
let ptr = env.allocate_temp::<ExternRef<StringKey>>(move_ref); let ptr = env.allocate_temp::<ExternRef<StringKey>>(move_ref);
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr); call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
*move_name = ptr.value().value(env).unwrap().clone(); *move_name = ptr
.value()
.value(env)?
.ok_or(anyhow!("Unable to get move name"))?
.clone();
} }
Ok(()) Ok(())
} }

View File

@ -1,6 +1,8 @@
use anyhow::anyhow;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc; use std::sync::Arc;
use anyhow_ext::Result;
use parking_lot::RwLock; use parking_lot::RwLock;
use paste::paste; use paste::paste;
@ -177,40 +179,50 @@ script_function_cache! {
impl ScriptFunctionCache { impl ScriptFunctionCache {
/// Get the name of a script. /// Get the name of a script.
pub(crate) fn script_get_name(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Option<TypedFunction<u32, u32>> { pub(crate) fn script_get_name(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Result<TypedFunction<u32, u32>> {
{ {
let read_lock = self.script_get_name.read(); let read_lock = self.script_get_name.read();
if let Some(f) = read_lock.as_ref() { if let Some(f) = read_lock.as_ref() {
return Some(f.clone()); return Ok(f.clone());
} }
} }
{ {
let exported = env.exported_functions(); let exported = env.exported_functions();
let f = exported.get::<StringKey>(&"script_get_name".into()); let f = exported.get::<StringKey>(&"script_get_name".into());
if let Some(f) = f { if let Some(f) = f {
let func: TypedFunction<u32, u32> = f.typed(&env.store_ref()).unwrap(); let func: TypedFunction<u32, u32> = f.typed(&env.store_ref())?;
let _ = self.script_get_name.write().insert(func); let _ = self.script_get_name.write().insert(func);
} }
} }
self.script_get_name.read().as_ref().cloned() Ok(self
.script_get_name
.read()
.as_ref()
.ok_or(anyhow!("Couldn't find script function `script_get_name`"))?
.clone())
} }
/// Drop the memory of a CString inside the WASM memory. /// Drop the memory of a CString inside the WASM memory.
pub(crate) fn dealloc_cstring(&self, env: &Arc<WebAssemblyEnvironmentData>) -> Option<TypedFunction<u32, ()>> { pub(crate) fn dealloc_cstring(&self, env: &Arc<WebAssemblyEnvironmentData>, ptr: u32) -> Result<()> {
{ {
let read_lock = self.dealloc_cstring.read(); let read_lock = self.dealloc_cstring.read();
if let Some(f) = read_lock.as_ref() { if read_lock.is_none() {
return Some(f.clone()); drop(read_lock);
}
}
{
let exported = env.exported_functions(); let exported = env.exported_functions();
let f = exported.get::<StringKey>(&"dealloc_cstring".into()); let f = exported.get::<StringKey>(&"dealloc_cstring".into());
if let Some(f) = f { if let Some(f) = f {
let func: TypedFunction<u32, ()> = f.typed(&env.store_ref()).unwrap(); let func: TypedFunction<u32, ()> = f.typed(&env.store_ref())?;
let _ = self.dealloc_cstring.write().insert(func); let _ = self.dealloc_cstring.write().insert(func);
} }
} }
self.dealloc_cstring.read().as_ref().cloned() };
let func = self
.dealloc_cstring
.read()
.as_ref()
.ok_or(anyhow!("Couldn't find script function `dealloc_cstring`"))?
.clone();
func.call(&mut env.store_mut(), ptr)?;
Ok(())
} }
} }

View File

@ -21,7 +21,7 @@ use crate::script_implementations::wasm::script_function_cache::ScriptFunctionCa
use crate::script_implementations::wasm::temp_wasm_allocator::{AllocatedObject, TempWasmAllocator}; use crate::script_implementations::wasm::temp_wasm_allocator::{AllocatedObject, TempWasmAllocator};
use crate::script_implementations::wasm::WebAssemblyScriptCapabilities; use crate::script_implementations::wasm::WebAssemblyScriptCapabilities;
use crate::static_data::Item; use crate::static_data::Item;
use crate::{ScriptCategory, StringKey, ValueIdentifiable, ValueIdentifier}; use crate::{ScriptCategory, StringKey, ValueIdentifiable, ValueIdentifier, VecExt};
/// A WebAssembly script resolver implements the dynamic scripts functionality with WebAssembly. /// A WebAssembly script resolver implements the dynamic scripts functionality with WebAssembly.
pub struct WebAssemblyScriptResolver { pub struct WebAssemblyScriptResolver {
@ -80,23 +80,30 @@ impl WebAssemblyScriptResolver {
/// Get an immutable reference to the current WASM Store. /// Get an immutable reference to the current WASM Store.
fn store_ref(&self) -> StoreRef<'_> { fn store_ref(&self) -> StoreRef<'_> {
unsafe { self._store.as_ref().unwrap().as_store_ref() } #[allow(clippy::unwrap_used)] // We know this is valid.
unsafe {
self._store.as_ref().unwrap().as_store_ref()
}
} }
/// Get a mutable reference to the current WASM Store. /// Get a mutable reference to the current WASM Store.
fn store_mut(&self) -> StoreMut<'_> { fn store_mut(&self) -> StoreMut<'_> {
unsafe { self._store.as_mut().unwrap().as_store_mut() } #[allow(clippy::unwrap_used)] // We know this is valid.
unsafe {
self._store.as_mut().unwrap().as_store_mut()
}
} }
/// Load a compiled WASM module. /// Load a compiled WASM module.
pub fn load_wasm_from_bytes(&mut self, bytes: &[u8]) { pub fn load_wasm_from_bytes(&mut self, bytes: &[u8]) -> Result<()> {
// FIXME: Error handling // FIXME: Error handling
let module = Module::new(&self.store_ref(), bytes).unwrap(); let module = Module::new(&self.store_ref(), bytes)?;
self.modules.push(module); self.modules.push(module);
Ok(())
} }
/// Tells the script resolver we're done loading wasm modules, and to finalize the resolver. /// Tells the script resolver we're done loading wasm modules, and to finalize the resolver.
pub fn finalize(&mut self) { pub fn finalize(&mut self) -> Result<()> {
let mut imports = Imports::new(); let mut imports = Imports::new();
let env = FunctionEnv::new( let env = FunctionEnv::new(
@ -115,12 +122,12 @@ impl WebAssemblyScriptResolver {
} }
} }
let instance = Instance::new(&mut self.store_mut(), module, &imports).unwrap(); let instance = Instance::new(&mut self.store_mut(), module, &imports)?;
let exports = &instance.exports; let exports = &instance.exports;
let init_fn = exports.get_extern("_init"); let init_fn = exports.get_extern("_init");
if let Some(Extern::Function(init_fn)) = init_fn { if let Some(Extern::Function(init_fn)) = init_fn {
init_fn.call(&mut self.store_mut(), &[]).unwrap(); init_fn.call(&mut self.store_mut(), &[])?;
} }
let mut exported_functions = self.environment_data.exported_functions.write(); let mut exported_functions = self.environment_data.exported_functions.write();
@ -136,19 +143,19 @@ impl WebAssemblyScriptResolver {
} }
} }
if let Some(m) = &self.environment_data.memory.read().as_ref() { if let Some(m) = &self.environment_data.memory.read().as_ref() {
m.grow(&mut self.store_mut(), 32).unwrap(); m.grow(&mut self.store_mut(), 32)?;
} }
if let Some(f) = exported_functions.get::<StringKey>(&"load_script".into()) { if let Some(f) = exported_functions.get::<StringKey>(&"load_script".into()) {
self.load_script_fn = Some(f.typed(&self.store_ref()).unwrap()) self.load_script_fn = Some(f.typed(&self.store_ref())?)
} }
if let Some(f) = exported_functions.get::<StringKey>(&"allocate_mem".into()) { if let Some(f) = exported_functions.get::<StringKey>(&"allocate_mem".into()) {
let _ = self let _ = self
.environment_data .environment_data
.allocate_mem_fn .allocate_mem_fn
.write() .write()
.insert(f.typed(&self.store_ref()).unwrap()); .insert(f.typed(&self.store_ref())?);
let temp_memory_slab = self.environment_data.allocate_mem(128, 1); let temp_memory_slab = self.environment_data.allocate_mem(128, 1)?;
let _ = self let _ = self
.environment_data .environment_data
.temp_allocator .temp_allocator
@ -157,6 +164,7 @@ impl WebAssemblyScriptResolver {
} }
self.instances.push(instance); self.instances.push(instance);
} }
Ok(())
} }
/// Gets the data passed to every function as environment data. /// Gets the data passed to every function as environment data.
@ -289,11 +297,13 @@ impl WebAssemblyEnvironmentData {
/// This returns the memory of the WASM container. /// This returns the memory of the WASM container.
pub fn memory(&self) -> *mut u8 { pub fn memory(&self) -> *mut u8 {
#[allow(clippy::unwrap_used)] // We know this is valid.
self.memory.read().as_ref().unwrap().view(&self.store_ref()).data_ptr() self.memory.read().as_ref().unwrap().view(&self.store_ref()).data_ptr()
} }
/// Return a pointer to something inside the WASM memory. /// Return a pointer to something inside the WASM memory.
pub fn get_raw_pointer<T>(&self, offset: u32) -> *mut T { pub fn get_raw_pointer<T>(&self, offset: u32) -> *mut T {
#[allow(clippy::unwrap_used)] // We know this is valid.
unsafe { unsafe {
self.memory self.memory
.read() .read()
@ -319,57 +329,55 @@ impl WebAssemblyEnvironmentData {
/// owned by WASM, and is how we can pass memory references that the host allocated to WASM. /// owned by WASM, and is how we can pass memory references that the host allocated to WASM.
/// The return is a tuple containing both the actual pointer to the memory (usable by the host), /// The return is a tuple containing both the actual pointer to the memory (usable by the host),
/// and the WASM offset to the memory (usable by the client). /// and the WASM offset to the memory (usable by the client).
pub fn allocate_mem(&self, size: u32, align: u32) -> (*mut u8, u32) { pub fn allocate_mem(&self, size: u32, align: u32) -> Result<(*mut u8, u32)> {
let wasm_ptr = self let wasm_ptr = self
.allocate_mem_fn .allocate_mem_fn
.read() .read()
.as_ref() .as_ref()
.unwrap() .ok_or(anyhow!("allocate_mem_fn not set"))?
.call(&mut self.store_mut(), size, align) .call(&mut self.store_mut(), size, align)?;
.unwrap(); unsafe { Ok((self.memory().offset(wasm_ptr as isize), wasm_ptr)) }
unsafe { (self.memory().offset(wasm_ptr as isize), wasm_ptr) }
} }
/// Allocates memory inside the WASM container with a given size and alignment. This memory is /// Allocates memory inside the WASM container with a given size and alignment. This memory is
/// owned by WASM, and is how we can pass memory references that the host allocated to WASM. /// owned by WASM, and is how we can pass memory references that the host allocated to WASM.
/// The return is a tuple containing both the actual pointer to the memory (usable by the host), /// The return is a tuple containing both the actual pointer to the memory (usable by the host),
/// and the WASM offset to the memory (usable by the client). /// and the WASM offset to the memory (usable by the client).
pub fn allocate_mem_typed<T>(&self) -> (*mut u8, u32) { pub fn allocate_mem_typed<T>(&self) -> Result<(*mut u8, u32)> {
let wasm_ptr = self let wasm_ptr = self
.allocate_mem_fn .allocate_mem_fn
.read() .read()
.as_ref() .as_ref()
.unwrap() .ok_or(anyhow!("allocate_mem_fn not set"))?
.call(&mut self.store_mut(), size_of::<T>() as u32, align_of::<T>() as u32) .call(&mut self.store_mut(), size_of::<T>() as u32, align_of::<T>() as u32)?;
.unwrap(); unsafe { Ok((self.memory().offset(wasm_ptr as isize), wasm_ptr)) }
unsafe { (self.memory().offset(wasm_ptr as isize), wasm_ptr) }
} }
/// Allocates a raw array in wasm, and copy the values from a given slice to it. Returns the /// Allocates a raw array in wasm, and copy the values from a given slice to it. Returns the
/// pointer in wasm memory. /// pointer in wasm memory.
pub fn copy_value_vec_to_wasm<T>(&self, v: &[T]) -> u32 { pub fn copy_value_vec_to_wasm<T>(&self, v: &[T]) -> Result<u32> {
let wasm_ptr = self let wasm_ptr = self
.allocate_mem_fn .allocate_mem_fn
.read() .read()
.as_ref() .as_ref()
.unwrap() .ok_or(anyhow!("allocate_mem_fn not set"))?
.call( .call(
&mut self.store_mut(), &mut self.store_mut(),
(std::mem::size_of_val(v)) as u32, (std::mem::size_of_val(v)) as u32,
align_of::<T>() as u32, align_of::<T>() as u32,
) )?;
.unwrap();
unsafe { unsafe {
let raw = self.memory().offset(wasm_ptr as isize) as *mut T; let raw = self.memory().offset(wasm_ptr as isize) as *mut T;
v.as_ptr().copy_to(raw, v.len()); v.as_ptr().copy_to(raw, v.len());
} }
wasm_ptr Ok(wasm_ptr)
} }
/// Allocate a piece of memory inside WASM with a very short lifespan. This is mainly used for /// Allocate a piece of memory inside WASM with a very short lifespan. This is mainly used for
/// rapid allocation of script function parameters, where WASM needs to write to a specific /// rapid allocation of script function parameters, where WASM needs to write to a specific
/// pointer. /// pointer.
pub(super) fn allocate_temp<T>(&self, value: T) -> AllocatedObject<T> { pub(super) fn allocate_temp<T>(&self, value: T) -> AllocatedObject<T> {
#[allow(clippy::unwrap_used)] // We know this is valid.
self.temp_allocator.read().as_ref().unwrap().alloc::<T>(value) self.temp_allocator.read().as_ref().unwrap().alloc::<T>(value)
} }
@ -401,10 +409,10 @@ impl WebAssemblyEnvironmentData {
} }
/// Get an extern ref belonging to a vector we have passed to WASM. /// Get an extern ref belonging to a vector we have passed to WASM.
pub fn get_extern_vec_ref_extern_ref(&self, extern_vec_ref: usize, index: usize) -> usize { pub fn get_extern_vec_ref_extern_ref(&self, extern_vec_ref: usize, index: usize) -> Result<usize> {
let r = self.extern_vec_ref_lookup.read(); let r = self.extern_vec_ref_lookup.read();
let v = r.get(&extern_vec_ref).unwrap(); let v = r.get(&extern_vec_ref).ok_or(anyhow!("Invalid extern vec ref"))?;
v[index] Ok(*v.get_res(index)?)
} }
/// Gets the extern ref index belonging to a specific pointer. If none exists, this will create /// Gets the extern ref index belonging to a specific pointer. If none exists, this will create
@ -438,9 +446,9 @@ impl WebAssemblyEnvironmentData {
/// Gets a value from the extern ref lookup. This turns an earlier registered index back into /// Gets a value from the extern ref lookup. This turns an earlier registered index back into
/// its proper value, validates its type, and returns the value. /// its proper value, validates its type, and returns the value.
pub fn get_extern_ref_value<'a, T: ?Sized>(&self, index: usize) -> &'a dyn Any { pub fn get_extern_ref_value<'a, T: ?Sized>(&self, index: usize) -> Result<&'a dyn Any> {
let read_guard = self.extern_ref_pointers.read(); let read_guard = self.extern_ref_pointers.read();
let ptr = read_guard.get(index - 1).unwrap(); let ptr = read_guard.get_res(index - 1)?;
if self if self
.extern_ref_type_lookup .extern_ref_type_lookup
.read() .read()
@ -449,14 +457,17 @@ impl WebAssemblyEnvironmentData {
is_vec: false, is_vec: false,
}) })
.is_none() .is_none()
{
#[allow(clippy::panic)] // Allow panic here, as this is a security error.
{ {
panic!( panic!(
"Extern ref was accessed with wrong type. Requested type {}, but this was not the type the extern ref was stored with.", "Extern ref was accessed with wrong type. Requested type {}, but this was not the type the extern ref was stored with.",
std::any::type_name::<T>() std::any::type_name::<T>()
); );
} }
}
unsafe { ptr.as_ref().unwrap() } unsafe { Ok(ptr.as_ref().unwrap()) }
} }
/// The WASM store. /// The WASM store.

View File

@ -75,6 +75,7 @@ impl<T> AllocatedObject<T> {
impl<T> Drop for AllocatedObject<T> { impl<T> Drop for AllocatedObject<T> {
fn drop(&mut self) { fn drop(&mut self) {
#[allow(clippy::unwrap_used)] // We know this is valid.
unsafe { unsafe {
self.allocator.as_ref().unwrap().drop::<T>(); self.allocator.as_ref().unwrap().drop::<T>();
} }

View File

@ -364,8 +364,8 @@ fn load_script_resolver(path: &String) -> Box<dyn ScriptResolver> {
let mut reader = BufReader::new(file); let mut reader = BufReader::new(file);
let mut buffer = Vec::new(); let mut buffer = Vec::new();
reader.read_to_end(&mut buffer).unwrap(); reader.read_to_end(&mut buffer).unwrap();
resolver.load_wasm_from_bytes(&buffer); resolver.load_wasm_from_bytes(&buffer).unwrap();
resolver.finalize(); resolver.finalize().unwrap();
resolver resolver
} }