PkmnLib_rs/src/script_implementations/wasm/extern_ref.rs

59 lines
1.8 KiB
Rust
Raw Normal View History

2022-07-18 08:16:47 +00:00
use std::marker::PhantomData;
use unique_type_id::UniqueTypeId;
use wasmer::FromToNativeWasmType;
use crate::script_implementations::wasm::script_resolver::{WebAssemblyEnv, WebAssemblyScriptResolver};
2022-07-18 08:16:47 +00:00
pub(crate) struct ExternRef<T: UniqueTypeId<u64>> {
index: u32,
_phantom: PhantomData<T>,
}
impl<T: UniqueTypeId<u64>> ExternRef<T> {
pub fn new(env: &WebAssemblyEnv, value: &T) -> Self {
Self {
index: env.resolver().get_extern_ref_index(value),
_phantom: Default::default(),
}
}
/// Creates an ExternRef with a given resolver. This can be used in cases where we do not have an environment variable.
pub(crate) fn new_with_resolver(resolver: &WebAssemblyScriptResolver, value: &T) -> Self {
2022-07-18 08:16:47 +00:00
Self {
index: resolver.environment_data().get_extern_ref_index(value),
2022-07-18 08:16:47 +00:00
_phantom: Default::default(),
}
}
/// An empty value ExternRef.
2022-07-18 08:16:47 +00:00
pub fn null() -> Self {
Self {
index: 0,
_phantom: Default::default(),
}
}
/// 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, 'b>(&'a self, env: &'b WebAssemblyEnv) -> Option<&'b T> {
2022-07-18 08:16:47 +00:00
let ptr = env.resolver().get_extern_ref_value(self.index) as *const T;
unsafe { ptr.as_ref() }
2022-07-18 08:16:47 +00:00
}
}
unsafe impl<T: UniqueTypeId<u64>> FromToNativeWasmType for ExternRef<T> {
type Native = i32;
fn from_native(native: Self::Native) -> Self {
Self {
index: native as u32,
_phantom: Default::default(),
}
}
fn to_native(self) -> Self::Native {
self.index as i32
}
}