Gen7ScriptsRs/pkmn_lib_interface/src/handling/extern_ref.rs

202 lines
4.2 KiB
Rust
Executable File

use crate::ImmutableList;
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::intrinsics::transmute;
use core::marker::PhantomData;
#[repr(C)]
pub struct ExternRef<T> {
p: u32,
resource_type: PhantomData<T>,
}
impl<T> ExternRef<T> {
pub fn is_null(&self) -> bool {
self.p == 0
}
pub(crate) fn get_internal_index(&self) -> u32 {
self.p
}
#[inline]
pub fn get_value(&self) -> Option<T>
where
T: ExternalReferenceType,
T: Sized,
T:,
{
T::instantiate_from_extern_value(*self)
}
#[inline]
pub fn not_null(&self) -> T
where
T: ExternalReferenceType,
T: Sized,
T:,
{
T::instantiate_from_extern_value(*self).unwrap()
}
#[inline]
pub(crate) fn cast<TCast>(&self) -> ExternRef<TCast> {
ExternRef::<TCast> {
p: self.p,
resource_type: Default::default(),
}
}
#[cfg(feature = "mock_data")]
pub(crate) fn mock() -> Self {
Self {
p: 0,
resource_type: Default::default(),
}
}
}
impl<T> Clone for ExternRef<T> {
fn clone(&self) -> Self {
Self {
p: self.p,
resource_type: Default::default(),
}
}
}
impl<T> Copy for ExternRef<T> {}
impl<T> Eq for ExternRef<T> {}
impl<T> PartialEq<Self> for ExternRef<T> {
fn eq(&self, other: &Self) -> bool {
u32::eq(&self.p, &other.p)
}
}
impl<T> PartialOrd<Self> for ExternRef<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
u32::partial_cmp(&self.p, &other.p)
}
}
impl<T> Ord for ExternRef<T> {
fn cmp(&self, other: &Self) -> Ordering {
u32::cmp(&self.p, &other.p)
}
}
impl<T> Hash for ExternRef<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.p.hash(state)
}
}
#[repr(C)]
pub struct VecExternRef<T> {
v: u64,
resource_type: PhantomData<T>,
}
impl<T> VecExternRef<T> {
pub fn is_null(&self) -> bool {
self.v == 0
}
pub(crate) fn get_internal_index(&self) -> u32 {
let v: (u32, u32) = unsafe { transmute(self.v) };
v.0
}
pub(crate) fn len(&self) -> u32 {
let v: (u32, u32) = unsafe { transmute(self.v) };
v.1
}
#[cfg(not(feature = "mock_data"))]
pub(crate) fn at(&self, index: u32) -> ExternRef<T> {
let p = unsafe { _vec_extern_ref_get_value(self.get_internal_index(), index) };
ExternRef {
p,
resource_type: Default::default(),
}
}
#[cfg(not(feature = "mock_data"))]
pub(crate) fn get_immutable_list(&self) -> ImmutableList<T>
where
T: Clone,
T: ExternalReferenceType,
{
ImmutableList::from_ref(*self)
}
}
impl<T> Clone for VecExternRef<T> {
fn clone(&self) -> Self {
Self {
v: self.v,
resource_type: Default::default(),
}
}
}
impl<T> Copy for VecExternRef<T> {}
impl<T> Eq for VecExternRef<T> {}
impl<T> PartialEq<Self> for VecExternRef<T> {
fn eq(&self, other: &Self) -> bool {
u64::eq(&self.v, &other.v)
}
}
impl<T> PartialOrd<Self> for VecExternRef<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
u64::partial_cmp(&self.v, &other.v)
}
}
impl<T> Ord for VecExternRef<T> {
fn cmp(&self, other: &Self) -> Ordering {
u64::cmp(&self.v, &other.v)
}
}
pub trait ExternalReferenceType {
fn from_extern_value(reference: ExternRef<Self>) -> Self
where
Self: Sized;
fn instantiate_from_extern_value(reference: ExternRef<Self>) -> Option<Self>
where
Self: Sized,
{
if reference.is_null() {
None
} else {
Some(Self::from_extern_value(reference))
}
}
}
#[macro_export]
macro_rules! impl_extern_ctor {
($name:ty) => {
impl $name {
pub(crate) fn new(ptr: ExternRef<Self>) -> Self {
Self { ptr }
}
pub(crate) fn ptr(&self) -> &ExternRef<Self> {
&self.ptr
}
}
};
}
#[cfg(not(feature = "mock_data"))]
extern "wasm" {
fn _vec_extern_ref_get_value(extern_ref: u32, index: u32) -> u32;
}