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 { p: u32, resource_type: PhantomData, } impl ExternRef { 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 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(&self) -> ExternRef { ExternRef:: { p: self.p, resource_type: Default::default(), } } #[cfg(feature = "mock_data")] pub(crate) fn mock() -> Self { Self { p: 0, resource_type: Default::default(), } } } impl Clone for ExternRef { fn clone(&self) -> Self { Self { p: self.p, resource_type: Default::default(), } } } impl Copy for ExternRef {} impl Eq for ExternRef {} impl PartialEq for ExternRef { fn eq(&self, other: &Self) -> bool { u32::eq(&self.p, &other.p) } } impl PartialOrd for ExternRef { fn partial_cmp(&self, other: &Self) -> Option { u32::partial_cmp(&self.p, &other.p) } } impl Ord for ExternRef { fn cmp(&self, other: &Self) -> Ordering { u32::cmp(&self.p, &other.p) } } impl Hash for ExternRef { fn hash(&self, state: &mut H) { self.p.hash(state) } } #[repr(C)] pub struct VecExternRef { v: u64, resource_type: PhantomData, } impl VecExternRef { 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 { 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 where T: Clone, T: ExternalReferenceType, { ImmutableList::from_ref(*self) } } impl Clone for VecExternRef { fn clone(&self) -> Self { Self { v: self.v, resource_type: Default::default(), } } } impl Copy for VecExternRef {} impl Eq for VecExternRef {} impl PartialEq for VecExternRef { fn eq(&self, other: &Self) -> bool { u64::eq(&self.v, &other.v) } } impl PartialOrd for VecExternRef { fn partial_cmp(&self, other: &Self) -> Option { u64::partial_cmp(&self.v, &other.v) } } impl Ord for VecExternRef { fn cmp(&self, other: &Self) -> Ordering { u64::cmp(&self.v, &other.v) } } pub trait ExternalReferenceType { fn from_extern_value(reference: ExternRef) -> Self where Self: Sized; fn instantiate_from_extern_value(reference: ExternRef) -> Option 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 { ptr } } pub(crate) fn ptr(&self) -> &ExternRef { &self.ptr } } }; } #[cfg(not(feature = "mock_data"))] extern "wasm" { fn _vec_extern_ref_get_value(extern_ref: u32, index: u32) -> u32; }