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
}
/// 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.
pub fn get_as<T: 'static>(&self) -> Result<MappedRwLockReadGuard<T>> {
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")]
mod web_assembly_script_resolver {
use crate::dynamic_data::ScriptResolver;
use crate::ffi::{ExternPointer, IdentifiablePointer};
use crate::ffi::{ExternPointer, IdentifiablePointer, NativeResult};
use crate::script_implementations::wasm::script_resolver::WebAssemblyScriptResolver;
/// Instantiates a new WebAssemblyScriptResolver.
@ -41,13 +41,19 @@ mod web_assembly_script_resolver {
mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>,
arr: *const u8,
len: usize,
) {
unsafe { ptr.as_mut().load_wasm_from_bytes(std::slice::from_raw_parts(arr, len)) }
) -> NativeResult<()> {
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.
#[no_mangle]
extern "C" fn webassembly_script_resolver_finalize(mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>) {
ptr.as_mut().finalize();
extern "C" fn webassembly_script_resolver_finalize(
mut ptr: ExternPointer<Box<WebAssemblyScriptResolver>>,
) -> NativeResult<()> {
ptr.as_mut().finalize().into()
}
}

View File

@ -25,6 +25,7 @@
#![feature(unboxed_closures)]
#![feature(trait_upcasting)]
#![feature(lazy_cell)]
#![feature(try_trait_v2)]
//! PkmnLib
//! 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.
#[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;

View File

@ -1,7 +1,7 @@
use crate::dynamic_data::{
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::script_resolver::WebAssemblyEnv;
use crate::StringKey;
@ -11,141 +11,141 @@ register! {
fn battle_get_pokemon_per_side(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
battle.value_func(&env).unwrap().pokemon_per_side()
) -> WasmResult<u8> {
Ok(battle.value_func(&env)?.pokemon_per_side()).into()
}
fn battle_get_parties(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> VecExternRef<BattleParty> {
VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env).unwrap().parties())
) -> WasmResult<VecExternRef<BattleParty>> {
Ok(VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env)?.parties())).into()
}
fn battle_get_choice_queue(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> ExternRef<ChoiceQueue> {
let queue = battle.value_func(&env).unwrap().current_turn_queue().read();
if let Some(queue) = queue.as_ref() {
) -> WasmResult<ExternRef<ChoiceQueue>> {
let queue = battle.value_func(&env)?.current_turn_queue().read();
Ok(if let Some(queue) = queue.as_ref() {
ExternRef::func_new(&env, queue)
} else {
ExternRef::null()
}
}).into()
}
fn battle_get_library(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> ExternRef<dyn DynamicLibrary> {
ExternRef::func_new(&env, &battle.value_func_arc(&env).unwrap().library().clone())
) -> WasmResult<ExternRef<dyn DynamicLibrary>> {
Ok(ExternRef::func_new(&env, &battle.value_func(&env)?.library().clone())).into()
}
fn battle_get_sides(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> VecExternRef<BattleSide> {
VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env).unwrap().sides())
) -> WasmResult<VecExternRef<BattleSide>> {
Ok(VecExternRef::new(env.data().data().as_ref(), battle.value_func(&env)?.sides())).into()
}
fn battle_get_random(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> ExternRef<BattleRandom> {
ExternRef::func_new(&env, battle.value_func(&env).unwrap().random())
) -> WasmResult<ExternRef<BattleRandom>> {
Ok(ExternRef::func_new(&env, battle.value_func(&env)?.random())).into()
}
fn battle_get_weather_name(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> ExternRef<StringKey> {
let weather = battle.value_func(&env).unwrap().weather_name().unwrap();
if let Some(weather) = weather {
) -> WasmResult<ExternRef<StringKey>> {
let weather = battle.value_func(&env)?.weather_name()?;
Ok(if let Some(weather) = weather {
ExternRef::func_new(&env, &weather)
} else {
ExternRef::null()
}
}).into()
}
fn battle_find_party_for_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
pokemon: ExternRef<Pokemon>
) -> ExternRef<BattleParty> {
let battle = battle.value_func(&env).unwrap();
let pokemon = pokemon.value_func(&env).unwrap();
) -> WasmResult<ExternRef<BattleParty>> {
let battle = battle.value_func(&env)?;
let pokemon = pokemon.value_func(&env)?;
for party in battle.parties() {
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(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
side: u8, index: u8
) -> ExternRef<Pokemon> {
let battle = battle.value_func(&env).unwrap();
) -> WasmResult<ExternRef<Pokemon>> {
let battle = battle.value_func(&env)?;
let pokemon = battle.get_pokemon(side, index);
if let Some(pokemon) = pokemon {
Ok(if let Some(pokemon) = pokemon {
ExternRef::func_new(&env, &pokemon)
} else {
ExternRef::null()
}
}).into()
}
fn battle_get_can_flee(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
if battle.value_func(&env).unwrap().can_flee() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if battle.value_func(&env)?.can_flee() { 1 } else { 0 }).into()
}
fn battle_get_number_of_sides(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
battle.value_func(&env).unwrap().number_of_sides()
) -> WasmResult<u8> {
Ok(battle.value_func(&env)?.number_of_sides()).into()
}
fn battle_get_has_ended(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
if battle.value_func(&env).unwrap().has_ended() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if battle.value_func(&env)?.has_ended() { 1 } else { 0 }).into()
}
fn battle_get_has_ended_conclusively(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
if battle.value_func(&env).unwrap().result().is_conclusive() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if battle.value_func(&env)?.result().is_conclusive() { 1 } else { 0 }).into()
}
fn battle_get_winning_side(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u8 {
if let BattleResult::Conclusive(result) = battle.value_func(&env).unwrap().result() {
) -> WasmResult<u8> {
Ok(if let BattleResult::Conclusive(result) = battle.value_func(&env)?.result() {
result
} else {
0
}
}).into()
}
fn battle_get_current_turn(
env: FunctionEnvMut<WebAssemblyEnv>,
battle: ExternRef<Battle>,
) -> u32 {
battle.value_func(&env).unwrap().current_turn()
) -> WasmResult<u32> {
Ok(battle.value_func(&env)?.current_turn()).into()
}
fn battle_party_get_party(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_party: ExternRef<BattleParty>,
) -> ExternRef<PokemonParty> {
ExternRef::func_new(&env, battle_party.value_func(&env).unwrap().party().as_ref())
) -> WasmResult<ExternRef<PokemonParty>> {
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::script_implementations::wasm::export_registry::register;
use crate::script_implementations::wasm::export_registry::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::ExternRef;
use wasmer::FunctionEnvMut;
@ -9,22 +9,22 @@ register! {
fn battle_random_get(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>,
) -> i32 {
battle_random.value_func(&env).unwrap().get().unwrap()
) -> WasmResult<i32> {
battle_random.value_func(&env)?.get().into()
}
fn battle_random_get_max(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>,
max: i32
) -> i32 {
battle_random.value_func(&env).unwrap().get_max(max).unwrap()
) -> WasmResult<i32> {
battle_random.value_func(&env)?.get_max(max).into()
}
fn battle_random_get_between(
env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<BattleRandom>,
min: i32,
max: i32
) -> i32 {
battle_random.value_func(&env).unwrap().get_between(min, max).unwrap()
) -> WasmResult<i32> {
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::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::script::WebAssemblyScript;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::ScriptCategory;
use anyhow::anyhow;
use std::ffi::CStr;
use wasmer::FunctionEnvMut;
@ -11,78 +12,78 @@ register! {
fn battleside_has_fled_battle(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
u8::from(side.value_func(&env).unwrap().has_fled_battle())
) -> WasmResult<u8> {
Ok(u8::from(side.value_func(&env)?.has_fled_battle())).into()
}
fn battleside_is_defeated(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
u8::from(side.value_func(&env).unwrap().is_defeated())
) -> WasmResult<u8> {
Ok(u8::from(side.value_func(&env)?.is_defeated())).into()
}
fn battleside_get_side_index(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
side.value_func(&env).unwrap().index()
) -> WasmResult<u8> {
Ok(side.value_func(&env)?.index()).into()
}
fn battleside_get_pokemon_per_side(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
side.value_func(&env).unwrap().pokemon_per_side()
) -> WasmResult<u8> {
Ok(side.value_func(&env)?.pokemon_per_side()).into()
}
fn battleside_get_battle(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> ExternRef<Battle> {
ExternRef::func_new(&env, side.value_func(&env).unwrap().battle().unwrap())
) -> WasmResult<ExternRef<Battle>> {
Ok(ExternRef::func_new(&env, side.value_func(&env)?.battle()?)).into()
}
fn battleside_get_pokemon(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
index: u32
) -> ExternRef<Pokemon> {
if let Some(Some(p)) = side.value_func(&env).unwrap().pokemon().get(index as usize) {
) -> WasmResult<ExternRef<Pokemon>> {
Ok(if let Some(Some(p)) = side.value_func(&env)?.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<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
if side.value_func(&env).unwrap().has_fled_battle() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if side.value_func(&env)?.has_fled_battle() { 1 } else { 0 }).into()
}
fn battle_side_get_is_defeated(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
) -> u8 {
if side.value_func(&env).unwrap().is_defeated() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if side.value_func(&env)?.is_defeated() { 1 } else { 0 }).into()
}
fn battleside_add_volatile_by_name(
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
name_ptr: u32
) -> u32 {
) -> WasmResult<u32> {
unsafe {
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();
if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>().unwrap();
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::<WebAssemblyScript>()?;
script.get_wasm_pointer()
} else {
0
}
}).into()
}
}
@ -90,22 +91,28 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
script_ptr: u32
) -> u32 {
let side : &BattleSide = side.value_func(&env).unwrap();
unsafe{
) -> WasmResult<u32> {
let side : &BattleSide = side.value_func(&env)?;
unsafe {
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 script = env.setup_script(script_ptr, ScriptCategory::Side, &c_name.as_ref().into(), side.into()).unwrap();
env.script_function_cache().dealloc_cstring(&env).unwrap().call(&mut env.store_mut(), name_ptr).unwrap();
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)?;
if let Some(script) = script {
let script = side.add_volatile_script_with_script(script);
let s = script.as_ref().unwrap().as_ref().unwrap().get_as::<WebAssemblyScript>().unwrap();
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::<WebAssemblyScript>()?;
s.get_wasm_pointer()
} else {
0
}
}).into()
}
}
@ -113,10 +120,10 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
name_ptr: u32
) -> u8 {
) -> WasmResult<u8> {
unsafe {
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>,
side: ExternRef<BattleSide>,
name_ptr: u32
) -> u32 {
) -> WasmResult<u32> {
unsafe {
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());
if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>().unwrap();
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::<WebAssemblyScript>()?;
script.get_wasm_pointer()
} else {
0
}
}).into()
}
}
@ -141,10 +148,10 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
side: ExternRef<BattleSide>,
name_ptr: u32
) {
) -> WasmResult<()> {
unsafe {
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::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::script_resolver::WebAssemblyEnv;
use wasmer::FunctionEnvMut;
@ -9,7 +9,7 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
battle_random: ExternRef<ChoiceQueue>,
pokemon: ExternRef<Pokemon>
) -> u8 {
u8::from(battle_random.value_func(&env).unwrap().move_pokemon_choice_next(pokemon.value_func(&env).unwrap()).unwrap())
) -> WasmResult<u8> {
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::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::script::WebAssemblyScript;
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
@ -10,29 +10,29 @@ register! {
fn executing_move_get_user(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<Pokemon> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().user().as_ref())
) -> WasmResult<ExternRef<Pokemon>> {
Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.user().as_ref())).into()
}
fn executing_move_get_use_move(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<dyn MoveData> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().use_move())
) -> WasmResult<ExternRef<dyn MoveData>> {
Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.use_move())).into()
}
fn executing_move_get_chosen_move(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> ExternRef<LearnedMove> {
ExternRef::func_new(&env, executing_move.value_func_arc(&env).unwrap().chosen_move().as_ref())
) -> WasmResult<ExternRef<LearnedMove>> {
Ok(ExternRef::func_new(&env, executing_move.value_func(&env)?.chosen_move().as_ref())).into()
}
fn executing_move_get_number_of_hits(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> u8 {
executing_move.value_func(&env).unwrap().number_of_hits()
) -> WasmResult<u8> {
Ok(executing_move.value_func(&env)?.number_of_hits()).into()
}
fn executing_move_get_hit_data(
@ -40,24 +40,24 @@ register! {
executing_move: ExternRef<ExecutingMove>,
target: ExternRef<Pokemon>,
hit: u8
) -> ExternRef<HitData> {
ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().get_hit_data(target.value_func(&env).unwrap(), hit).unwrap())
) -> WasmResult<ExternRef<HitData>> {
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(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> u32 {
executing_move.value_func(&env).unwrap().target_count() as u32
) -> WasmResult<u32> {
Ok(executing_move.value_func(&env)?.target_count() as u32).into()
}
fn executing_move_is_pokemon_target(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
pokemon: ExternRef<Pokemon>
) -> u8 {
let pokemon = pokemon.value_func_arc(&env).unwrap();
if executing_move.value_func(&env).unwrap().is_pokemon_target(&pokemon) { 1 } else { 0 }
) -> WasmResult<u8> {
let pokemon = pokemon.value_func_arc(&env)?;
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(
env: FunctionEnvMut<WebAssemblyEnv>,
executing_move: ExternRef<ExecutingMove>,
) -> (u32 , u32) {
let executing_move = executing_move.value_func(&env).unwrap();
if let Some(script) = executing_move.script().get() {
let read_lock = script.read();
if let Some(script) = read_lock.as_ref() {
let s = script.as_any().downcast_ref::<WebAssemblyScript>().unwrap().get_wasm_pointer();
return (s, s + 4)
}
) -> WasmResult<(u32 , u32)> {
let executing_move = executing_move.value_func(&env)?;
let script = executing_move.script();
if script.is_any() {
let s = script.get_as::<WebAssemblyScript>()?.get_wasm_pointer();
return Ok((s, s + 4)).into()
}
(0, 0)
Ok((0, 0)).into()
}
}

View File

@ -2,13 +2,14 @@ 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;
use crate::script_implementations::wasm::export_registry::{register, 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::{Ability, ClampedStatisticSet, Form, Nature, Species};
use crate::static_data::{Item, StatisticSet};
use crate::ScriptCategory;
use crate::{ScriptCategory, VecExt};
use anyhow::anyhow;
use std::ffi::{c_char, CStr, CString};
use wasmer::FunctionEnvMut;
@ -16,88 +17,89 @@ register! {
fn pokemon_get_library(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn DynamicLibrary> {
let lib = pokemon.value_func(&env).unwrap().library().clone();
ExternRef::func_new(&env, &lib)
) -> WasmResult<ExternRef<dyn DynamicLibrary>> {
let lib = pokemon.value_func(&env)?.library().clone();
Ok(ExternRef::func_new(&env, &lib)).into()
}
fn pokemon_get_boosted_stats(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<StatisticSet<u32>> {
let statistic_set = pokemon.value_func(&env).unwrap().boosted_stats();
ExternRef::func_new(&env, statistic_set)
) -> WasmResult<ExternRef<StatisticSet<u32>>> {
let statistic_set = pokemon.value_func(&env)?.boosted_stats();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_flat_stats(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<StatisticSet<u32>> {
let statistic_set = pokemon.value_func(&env).unwrap().flat_stats();
ExternRef::func_new(&env, statistic_set)
) -> WasmResult<ExternRef<StatisticSet<u32>>> {
let statistic_set = pokemon.value_func(&env)?.flat_stats();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_stat_boosts(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<i8, -6, 6>> {
let statistic_set = pokemon.value_func(&env).unwrap().stat_boosts();
ExternRef::func_new(&env, statistic_set)
) -> WasmResult<ExternRef<ClampedStatisticSet<i8, -6, 6>>> {
let statistic_set = pokemon.value_func(&env)?.stat_boosts();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_individual_values(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<u8, 0, 31>> {
let statistic_set = pokemon.value_func(&env).unwrap().individual_values();
ExternRef::func_new(&env, statistic_set)
) -> WasmResult<ExternRef<ClampedStatisticSet<u8, 0, 31>>> {
let statistic_set = pokemon.value_func(&env)?.individual_values();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_effort_values(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<ClampedStatisticSet<u8, 0, 252>> {
let statistic_set = pokemon.value_func(&env).unwrap().effort_values();
ExternRef::func_new(&env, statistic_set)
) -> WasmResult<ExternRef<ClampedStatisticSet<u8, 0, 252>>> {
let statistic_set = pokemon.value_func(&env)?.effort_values();
Ok(ExternRef::func_new(&env, statistic_set)).into()
}
fn pokemon_get_species(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Species> {
let species = pokemon.value_func(&env).unwrap().species();
ExternRef::func_new(&env, &species)
) -> WasmResult<ExternRef<dyn Species>> {
let species = pokemon.value_func(&env)?.species();
Ok(ExternRef::func_new(&env, &species)).into()
}
fn pokemon_get_weight(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> f32 {
pokemon.value_func(&env).unwrap().weight()
) -> WasmResult<f32> {
Ok(pokemon.value_func(&env)?.weight()).into()
}
fn pokemon_set_weight(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
weight: f32,
) {
pokemon.value_func(&env).unwrap().set_weight(weight)
) -> WasmResult<()> {
pokemon.value_func(&env)?.set_weight(weight);
Ok(()).into()
}
fn pokemon_get_height(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> f32 {
pokemon.value_func(&env).unwrap().height()
) -> WasmResult<f32> {
Ok(pokemon.value_func(&env)?.height()).into()
}
fn pokemon_get_gender(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
) -> WasmResult<u8> {
unsafe {
transmute(pokemon.value_func(&env).unwrap().gender())
Ok(transmute(pokemon.value_func(&env)?.gender())).into()
}
}
@ -106,9 +108,10 @@ register! {
pokemon: ExternRef<Pokemon>,
damage: u32,
source: u8
) {
) -> WasmResult<()> {
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>,
pokemon: ExternRef<Pokemon>,
index: u32
) -> ExternRef<LearnedMove> {
let read_lock = pokemon.value_func(&env).unwrap().learned_moves().read();
) -> WasmResult<ExternRef<LearnedMove>> {
let read_lock = pokemon.value_func(&env)?.learned_moves().read();
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)
}
else{
ExternRef::null()
}
}).into()
}
fn pokemon_change_stat_boost(
@ -133,65 +136,65 @@ register! {
stat: u8,
amount: i8,
self_inflicted: u8
) -> u8 {
) -> WasmResult<u8> {
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(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<Battle> {
if let Some(battle) = pokemon.value_func(&env).unwrap().get_battle() {
) -> WasmResult<ExternRef<Battle>> {
Ok(if let Some(battle) = pokemon.value_func(&env)?.get_battle() {
ExternRef::func_new(&env, battle)
} else {
ExternRef::null()
}
}).into()
}
fn pokemon_get_battle_index(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_index() {
) -> WasmResult<u8> {
Ok(if let Some(i) = pokemon.value_func(&env)?.get_battle_index() {
i
} else {
255
}
}).into()
}
fn pokemon_get_battle_side_index(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if let Some(i) = pokemon.value_func(&env).unwrap().get_battle_side_index() {
) -> WasmResult<u8> {
Ok(if let Some(i) = pokemon.value_func(&env)?.get_battle_side_index() {
i
} else {
255
}
}).into()
}
fn pokemon_get_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Item> {
let read_lock = pokemon.value_func(&env).unwrap().held_item().read();
if let Some(item) = read_lock.as_ref() {
) -> WasmResult<ExternRef<dyn Item>> {
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())
} else {
ExternRef::null()
}
}).into()
}
fn pokemon_has_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name: u32
) -> u8 {
) -> WasmResult<u8> {
let name : *mut c_char = env.data().data().get_raw_pointer(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(
@ -199,51 +202,52 @@ register! {
pokemon: ExternRef<Pokemon>,
amount: u32,
allow_revive: u8
) -> u8 {
u8::from(pokemon.value_func(&env).unwrap().heal(amount, allow_revive == 1))
) -> WasmResult<u8> {
Ok(u8::from(pokemon.value_func(&env)?.heal(amount, allow_revive == 1))).into()
}
fn pokemon_clear_status(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) {
pokemon.value_func(&env).unwrap().clear_status()
) -> WasmResult<()> {
pokemon.value_func(&env)?.clear_status();
WasmResult::ok(())
}
fn pokemon_get_active_ability(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Ability> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().active_ability())
) -> WasmResult<ExternRef<dyn Ability>> {
Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.active_ability())).into()
}
fn pokemon_get_real_ability(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> (u8, u8) {
let index = &pokemon.value_func(&env).unwrap().real_ability();
(if index.hidden { 1 } else { 0 }, index.index)
) -> WasmResult<(u8, u8)> {
let index = &pokemon.value_func(&env)?.real_ability();
WasmResult::ok((if index.hidden { 1 } else { 0 }, index.index))
}
fn pokemon_get_is_ability_overriden(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if pokemon.value_func(&env).unwrap().is_ability_overriden() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.is_ability_overriden() { 1 } else { 0 }).into()
}
fn pokemon_get_allowed_experience_gain(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if pokemon.value_func(&env).unwrap().allowed_experience_gain() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.allowed_experience_gain() { 1 } else { 0 }).into()
}
fn pokemon_get_is_usable(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if pokemon.value_func(&env).unwrap().is_usable() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.is_usable() { 1 } else { 0 }).into()
}
@ -251,56 +255,56 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
item: ExternRef<dyn Item>
) -> ExternRef<dyn Item> {
let item = item.value_func_arc(&env).unwrap();
let old_item = pokemon.value_func(&env).unwrap().set_held_item(&item);
if let Some(old_item) = old_item {
) -> WasmResult<ExternRef<dyn Item>> {
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)
} else {
ExternRef::null()
}
}).into()
}
fn pokemon_remove_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Item> {
let old_item = pokemon.value_func(&env).unwrap().remove_held_item();
if let Some(old_item) = old_item {
) -> WasmResult<ExternRef<dyn Item>> {
let old_item = pokemon.value_func(&env)?.remove_held_item();
Ok(if let Some(old_item) = old_item {
ExternRef::func_new(&env, &old_item)
} else {
ExternRef::null()
}
}).into()
}
fn pokemon_consume_held_item(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
if pokemon.value_func(&env).unwrap().consume_held_item().unwrap() { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.consume_held_item()? { 1 } else { 0 }).into()
}
fn pokemon_get_types_length(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>
) -> u32 {
pokemon.value_func(&env).unwrap().types().len() as u32
) -> WasmResult<u32> {
Ok(pokemon.value_func(&env)?.types().len() as u32).into()
}
fn pokemon_get_type(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
index: u32
) -> u8 {
(*pokemon.value_func(&env).unwrap().types().get(index as usize).unwrap()).into()
) -> WasmResult<u8> {
Ok((*pokemon.value_func(&env)?.types().get_res(index as usize)?).into()).into()
}
fn pokemon_has_type(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
t: u8
) -> u8 {
if pokemon.value_func(&env).unwrap().types().contains(&t.into()) { 1 } else { 0 }
) -> WasmResult<u8> {
Ok(if pokemon.value_func(&env)?.types().contains(&t.into()) { 1 } else { 0 }).into()
}
fn pokemon_change_species(
@ -308,97 +312,102 @@ register! {
pokemon: ExternRef<Pokemon>,
species: ExternRef<dyn Species>,
form: ExternRef<dyn Form>,
) {
pokemon.value_func(&env).unwrap().change_species(
species.value_func_arc(&env).unwrap(),
form.value_func_arc(&env).unwrap(),
).unwrap();
) -> WasmResult<()> {
pokemon.value_func(&env)?.change_species(
species.value_func_arc(&env)?,
form.value_func_arc(&env)?,
)?;
WasmResult::ok(())
}
fn pokemon_change_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
form: ExternRef<dyn Form>,
) {
pokemon.value_func(&env).unwrap().change_form(
&form.value_func_arc(&env).unwrap(),
).unwrap();
) -> WasmResult<()> {
pokemon.value_func(&env)?.change_form(
&form.value_func_arc(&env)?,
)?;
WasmResult::ok(())
}
fn pokemon_get_current_health(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
pokemon.value_func(&env).unwrap().current_health()
) -> WasmResult<u32> {
Ok(pokemon.value_func(&env)?.current_health()).into()
}
fn pokemon_get_nature(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Nature> {
ExternRef::func_new(&env, pokemon.value_func(&env).unwrap().nature())
) -> WasmResult<ExternRef<dyn Nature>> {
Ok(ExternRef::func_new(&env, pokemon.value_func(&env)?.nature())).into()
}
fn pokemon_get_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Form> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().form())
) -> WasmResult<ExternRef<dyn Form>> {
Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.form())).into()
}
fn pokemon_get_display_species(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Species> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().display_species())
) -> WasmResult<ExternRef<dyn Species>> {
Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.display_species())).into()
}
fn pokemon_get_display_form(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> ExternRef<dyn Form> {
ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().display_form())
) -> WasmResult<ExternRef<dyn Form>> {
Ok(ExternRef::func_new(&env, &pokemon.value_func(&env)?.display_form())).into()
}
fn pokemon_get_level(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> LevelInt {
pokemon.value_func(&env).unwrap().level()
) -> WasmResult<LevelInt> {
Ok(pokemon.value_func(&env)?.level()).into()
}
fn pokemon_get_experience(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
pokemon.value_func(&env).unwrap().experience()
) -> WasmResult<u32> {
Ok(pokemon.value_func(&env)?.experience()).into()
}
fn pokemon_get_unique_identifier(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
pokemon.value_func(&env).unwrap().unique_identifier()
) -> WasmResult<u32> {
Ok(pokemon.value_func(&env)?.unique_identifier()).into()
}
fn pokemon_get_coloring(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u8 {
pokemon.value_func(&env).unwrap().coloring()
) -> WasmResult<u8> {
Ok(pokemon.value_func(&env)?.coloring()).into()
}
fn pokemon_get_nickname(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
let pokemon = pokemon.value_func(&env).unwrap();
) -> WasmResult<u32> {
let pokemon = pokemon.value_func(&env)?;
let nickname = pokemon.nickname();
if let Some(nickname) = nickname {
let nickname: CString = CString::new(nickname.as_str()).unwrap();
env.data().data().copy_value_vec_to_wasm(nickname.as_bytes())
let nickname: CString = match CString::new(nickname.as_str()) {
Ok(nickname) => nickname,
Err(e) => return WasmResult::err(e.into()),
};
env.data().data().copy_value_vec_to_wasm(nickname.as_bytes()).into()
} else {
0
Ok(0).into()
}
}
@ -408,15 +417,15 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name_ptr: u32
) -> u32 {
) -> WasmResult<u32> {
unsafe {
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 {
let script = script.get_as::<WebAssemblyScript>().unwrap();
script.get_wasm_pointer()
let script = script.get_as::<WebAssemblyScript>()?;
Ok(script.get_wasm_pointer()).into()
} else {
0
Ok(0).into()
}
}
}
@ -425,21 +434,24 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
script_ptr: u32
) -> u32 {
let pokemon : &Pokemon = pokemon.value_func(&env).unwrap();
) -> WasmResult<u32> {
let pokemon : &Pokemon = pokemon.value_func(&env)?;
unsafe{
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 script = env.setup_script(script_ptr, ScriptCategory::Pokemon, &c_name.as_ref().into(), pokemon.into()).unwrap();
env.script_function_cache().dealloc_cstring(&env).unwrap().call(&mut env.store_mut(), name_ptr).unwrap();
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)?;
if let Some(script) = script {
let script = pokemon.add_volatile_script_with_script(script);
let s = script.as_ref().unwrap().as_ref().unwrap().get_as::<WebAssemblyScript>().unwrap();
s.get_wasm_pointer()
let script = pokemon.add_volatile_script_with_script(script)?;
let s = script.as_ref().ok_or(anyhow!("Unable to get script"))?.get_as::<WebAssemblyScript>()?;
WasmResult::ok(s.get_wasm_pointer())
} else {
0
WasmResult::ok(0)
}
}
}
@ -448,10 +460,10 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name_ptr: u32
) -> u8 {
) -> WasmResult<u8> {
unsafe {
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>,
pokemon: ExternRef<Pokemon>,
name_ptr: u32
) -> u32 {
) -> WasmResult<u32> {
unsafe {
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());
if let Some(script) = script {
let script = script.get_as::<WebAssemblyScript>().unwrap();
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::<WebAssemblyScript>()?;
script.get_wasm_pointer()
} else {
0
}
}).into()
}
}
@ -476,25 +488,24 @@ register! {
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
name_ptr: u32
) {
) -> WasmResult<()> {
unsafe {
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(
env: FunctionEnvMut<WebAssemblyEnv>,
pokemon: ExternRef<Pokemon>,
) -> u32 {
let pokemon = pokemon.value_func(&env).unwrap();
if let Some(script) = pokemon.ability_script().get() {
let read_lock = script.read();
if let Some(script) = read_lock.as_ref() {
return script.as_any().downcast_ref::<WebAssemblyScript>().unwrap().get_wasm_pointer()
}
) -> WasmResult<u32> {
let pokemon = pokemon.value_func(&env)?;
let script = pokemon.ability_script();
if script.is_any() {
return Ok(script.get_as::<WebAssemblyScript>()?.get_wasm_pointer()).into();
}
0
WasmResult::ok(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::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::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
fn _vec_extern_ref_get_value(env: FunctionEnvMut<WebAssemblyEnv>, reference: u32, index: u32) -> u32 {
env.data()
fn _vec_extern_ref_get_value(env: FunctionEnvMut<WebAssemblyEnv>, reference: u32, index: u32) -> WasmResult<u32> {
let res = env
.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.
fn string_key_get_hash(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 {
string_key.value_func(&env).unwrap().hash()
fn string_key_get_hash(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> WasmResult<u32> {
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
/// memory, so this is relatively heavy.
fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 {
let string_key = string_key.value_func(&env).unwrap().str();
fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> WasmResult<u32> {
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::<CString>() as u32);
.allocate_mem((string_key.len() + 1) as u32, align_of::<CString>() as u32)?;
let mut wasm_string: Vec<u8> =
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);
wasm_string_ptr.1
Ok(wasm_string_ptr.1).into()
}
/// Gets the type of an EffectParameter
fn effect_parameter_get_type(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 {
let v = parameter.value_func(&env).unwrap();
match v {
fn effect_parameter_get_type(
env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>,
) -> WasmResult<u8> {
let v = parameter.value_func(&env)?;
Ok(match v {
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.
fn effect_parameter_as_bool(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 {
let v = parameter.value_func(&env).unwrap();
fn effect_parameter_as_bool(
env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>,
) -> WasmResult<u8> {
let v = parameter.value_func(&env)?;
match v {
EffectParameter::Bool(_, b) => u8::from(*b),
_ => panic!("Unexpected parameter type!"),
EffectParameter::Bool(_, b) => Ok(<u8 as From<bool>>::from(*b)),
_ => 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.
fn effect_parameter_as_int(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> i64 {
let v = parameter.value_func(&env).unwrap();
fn effect_parameter_as_int(
env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>,
) -> WasmResult<i64> {
let v = parameter.value_func(&env)?;
match v {
EffectParameter::Int(_, i) => *i,
_ => panic!("Unexpected parameter type!"),
EffectParameter::Int(_, i) => Ok(*i),
_ => 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.
fn effect_parameter_as_float(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> f32 {
let v = parameter.value_func(&env).unwrap();
fn effect_parameter_as_float(
env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>,
) -> WasmResult<f32> {
let v = parameter.value_func(&env)?;
match v {
EffectParameter::Float(_, f) => *f,
_ => panic!("Unexpected parameter type!"),
EffectParameter::Float(_, f) => Ok(*f),
_ => 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.
fn effect_parameter_as_string(
env: FunctionEnvMut<WebAssemblyEnv>,
parameter: ExternRef<EffectParameter>,
) -> ExternRef<StringKey> {
let v = parameter.value_func(&env).unwrap();
) -> WasmResult<ExternRef<StringKey>> {
let v = parameter.value_func(&env)?;
match v {
EffectParameter::String(_, s) => ExternRef::func_new(&env, s),
_ => panic!("Unexpected parameter type!"),
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<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::{register, WasmResult};
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
use crate::static_data::{Form, StatisticSet};
@ -18,11 +18,11 @@ fn form_get_name(
fn form_get_types(
env: FunctionEnvMut<WebAssemblyEnv>,
form: ExternRef<dyn Form>
) -> (u32, u32) {
) -> WasmResult<(u32, u32)> {
let form = form.value_func_arc(&env).unwrap();
let vec = form.types();
let wasm_ptr = env.data().data().copy_value_vec_to_wasm(vec);
(wasm_ptr, vec.len() as u32)
let wasm_ptr = env.data().data().copy_value_vec_to_wasm(vec)?;
Ok((wasm_ptr, vec.len() as u32)).into()
}
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::marker::PhantomData;
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
/// 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
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
/// 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
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
/// 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
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
/// 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
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
/// 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
T: 'static,
{
env.get_extern_ref_value::<T>(self.index)
Ok(env
.get_extern_ref_value::<T>(self.index)?
.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
/// 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
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::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::Arc;
@ -189,7 +189,11 @@ impl Script for WebAssemblyScript {
let move_ref = ex_ref!(env, move_name);
let ptr = env.allocate_temp::<ExternRef<StringKey>>(move_ref);
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(())
}

View File

@ -1,6 +1,8 @@
use anyhow::anyhow;
use std::marker::PhantomData;
use std::sync::Arc;
use anyhow_ext::Result;
use parking_lot::RwLock;
use paste::paste;
@ -177,40 +179,50 @@ script_function_cache! {
impl ScriptFunctionCache {
/// 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();
if let Some(f) = read_lock.as_ref() {
return Some(f.clone());
return Ok(f.clone());
}
}
{
let exported = env.exported_functions();
let f = exported.get::<StringKey>(&"script_get_name".into());
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);
}
}
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.
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();
if let Some(f) = read_lock.as_ref() {
return Some(f.clone());
if read_lock.is_none() {
drop(read_lock);
let exported = env.exported_functions();
let f = exported.get::<StringKey>(&"dealloc_cstring".into());
if let Some(f) = f {
let func: TypedFunction<u32, ()> = f.typed(&env.store_ref())?;
let _ = self.dealloc_cstring.write().insert(func);
}
}
}
{
let exported = env.exported_functions();
let f = exported.get::<StringKey>(&"dealloc_cstring".into());
if let Some(f) = f {
let func: TypedFunction<u32, ()> = f.typed(&env.store_ref()).unwrap();
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::WebAssemblyScriptCapabilities;
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.
pub struct WebAssemblyScriptResolver {
@ -80,23 +80,30 @@ impl WebAssemblyScriptResolver {
/// Get an immutable reference to the current WASM Store.
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.
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.
pub fn load_wasm_from_bytes(&mut self, bytes: &[u8]) {
pub fn load_wasm_from_bytes(&mut self, bytes: &[u8]) -> Result<()> {
// FIXME: Error handling
let module = Module::new(&self.store_ref(), bytes).unwrap();
let module = Module::new(&self.store_ref(), bytes)?;
self.modules.push(module);
Ok(())
}
/// 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 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 init_fn = exports.get_extern("_init");
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();
@ -136,19 +143,19 @@ impl WebAssemblyScriptResolver {
}
}
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()) {
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()) {
let _ = self
.environment_data
.allocate_mem_fn
.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
.environment_data
.temp_allocator
@ -157,6 +164,7 @@ impl WebAssemblyScriptResolver {
}
self.instances.push(instance);
}
Ok(())
}
/// Gets the data passed to every function as environment data.
@ -289,11 +297,13 @@ impl WebAssemblyEnvironmentData {
/// This returns the memory of the WASM container.
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()
}
/// Return a pointer to something inside the WASM memory.
pub fn get_raw_pointer<T>(&self, offset: u32) -> *mut T {
#[allow(clippy::unwrap_used)] // We know this is valid.
unsafe {
self.memory
.read()
@ -319,57 +329,55 @@ impl WebAssemblyEnvironmentData {
/// 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),
/// 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
.allocate_mem_fn
.read()
.as_ref()
.unwrap()
.call(&mut self.store_mut(), size, align)
.unwrap();
unsafe { (self.memory().offset(wasm_ptr as isize), wasm_ptr) }
.ok_or(anyhow!("allocate_mem_fn not set"))?
.call(&mut self.store_mut(), size, align)?;
unsafe { Ok((self.memory().offset(wasm_ptr as isize), wasm_ptr)) }
}
/// 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.
/// 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).
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
.allocate_mem_fn
.read()
.as_ref()
.unwrap()
.call(&mut self.store_mut(), size_of::<T>() as u32, align_of::<T>() as u32)
.unwrap();
unsafe { (self.memory().offset(wasm_ptr as isize), wasm_ptr) }
.ok_or(anyhow!("allocate_mem_fn not set"))?
.call(&mut self.store_mut(), size_of::<T>() as u32, align_of::<T>() as u32)?;
unsafe { Ok((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
/// 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
.allocate_mem_fn
.read()
.as_ref()
.unwrap()
.ok_or(anyhow!("allocate_mem_fn not set"))?
.call(
&mut self.store_mut(),
(std::mem::size_of_val(v)) as u32,
align_of::<T>() as u32,
)
.unwrap();
)?;
unsafe {
let raw = self.memory().offset(wasm_ptr as isize) as *mut T;
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
/// rapid allocation of script function parameters, where WASM needs to write to a specific
/// pointer.
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)
}
@ -401,10 +409,10 @@ impl WebAssemblyEnvironmentData {
}
/// 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 v = r.get(&extern_vec_ref).unwrap();
v[index]
let v = r.get(&extern_vec_ref).ok_or(anyhow!("Invalid extern vec ref"))?;
Ok(*v.get_res(index)?)
}
/// 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
/// 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 ptr = read_guard.get(index - 1).unwrap();
let ptr = read_guard.get_res(index - 1)?;
if self
.extern_ref_type_lookup
.read()
@ -450,13 +458,16 @@ impl WebAssemblyEnvironmentData {
})
.is_none()
{
panic!(
"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>()
);
#[allow(clippy::panic)] // Allow panic here, as this is a security error.
{
panic!(
"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>()
);
}
}
unsafe { ptr.as_ref().unwrap() }
unsafe { Ok(ptr.as_ref().unwrap()) }
}
/// The WASM store.

View File

@ -75,6 +75,7 @@ impl<T> AllocatedObject<T> {
impl<T> Drop for AllocatedObject<T> {
fn drop(&mut self) {
#[allow(clippy::unwrap_used)] // We know this is valid.
unsafe {
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 buffer = Vec::new();
reader.read_to_end(&mut buffer).unwrap();
resolver.load_wasm_from_bytes(&buffer);
resolver.finalize();
resolver.load_wasm_from_bytes(&buffer).unwrap();
resolver.finalize().unwrap();
resolver
}