use std::{any::Any, marker::PhantomData};
use crate::js::{StoreHandle, StoreObjects};
use crate::js::{AsStoreMut, AsStoreRef, StoreMut, StoreRef};
#[derive(Debug)]
#[repr(transparent)]
pub struct FunctionEnv<T> {
pub(crate) handle: StoreHandle<VMFunctionEnvironment>,
marker: PhantomData<T>,
}
impl<T> FunctionEnv<T> {
pub fn new(store: &mut impl AsStoreMut, value: T) -> Self
where
T: Any + Send + 'static + Sized,
{
Self {
handle: StoreHandle::new(
store.as_store_mut().objects_mut(),
VMFunctionEnvironment::new(value),
),
marker: PhantomData,
}
}
pub(crate) fn from_handle(handle: StoreHandle<VMFunctionEnvironment>) -> Self {
Self {
handle,
marker: PhantomData,
}
}
pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T
where
T: Any + Send + 'static + Sized,
{
self.handle
.get(store.as_store_ref().objects())
.as_ref()
.downcast_ref::<T>()
.unwrap()
}
pub fn as_mut<'a>(&self, store: &'a mut impl AsStoreMut) -> &'a mut T
where
T: Any + Send + 'static + Sized,
{
self.handle
.get_mut(store.objects_mut())
.as_mut()
.downcast_mut::<T>()
.unwrap()
}
pub fn into_mut(self, store: &mut impl AsStoreMut) -> FunctionEnvMut<T>
where
T: Any + Send + 'static + Sized,
{
FunctionEnvMut {
store_mut: store.as_store_mut(),
func_env: self,
}
}
}
impl<T> PartialEq for FunctionEnv<T> {
fn eq(&self, other: &Self) -> bool {
self.handle == other.handle
}
}
impl<T> Eq for FunctionEnv<T> {}
impl<T> std::hash::Hash for FunctionEnv<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.handle.hash(state);
self.marker.hash(state);
}
}
impl<T> Clone for FunctionEnv<T> {
fn clone(&self) -> Self {
Self {
handle: self.handle.clone(),
marker: self.marker,
}
}
}
pub struct FunctionEnvMut<'a, T: 'a> {
pub(crate) store_mut: StoreMut<'a>,
pub(crate) func_env: FunctionEnv<T>,
}
impl<T: Send + 'static> FunctionEnvMut<'_, T> {
pub fn data(&self) -> &T {
self.func_env.as_ref(&self.store_mut)
}
pub fn data_mut<'a>(&'a mut self) -> &'a mut T {
self.func_env.as_mut(&mut self.store_mut)
}
pub fn as_ref(&self) -> FunctionEnv<T> {
self.func_env.clone()
}
pub fn as_mut<'a>(&'a mut self) -> FunctionEnvMut<'a, T> {
FunctionEnvMut {
store_mut: self.store_mut.as_store_mut(),
func_env: self.func_env.clone(),
}
}
}
impl<T> AsStoreRef for FunctionEnvMut<'_, T> {
fn as_store_ref(&self) -> StoreRef<'_> {
StoreRef {
inner: self.store_mut.inner,
}
}
}
impl<T> AsStoreMut for FunctionEnvMut<'_, T> {
fn as_store_mut(&mut self) -> StoreMut<'_> {
StoreMut {
inner: self.store_mut.inner,
}
}
#[inline]
fn objects_mut(&mut self) -> &mut StoreObjects {
&mut self.store_mut.inner.objects
}
}
pub struct VMFunctionEnvironment {
contents: Box<dyn Any + Send + 'static>,
}
impl VMFunctionEnvironment {
pub fn new(val: impl Any + Send + 'static) -> Self {
Self {
contents: Box::new(val),
}
}
#[allow(clippy::should_implement_trait)]
pub fn as_ref(&self) -> &(dyn Any + Send + 'static) {
&*self.contents
}
#[allow(clippy::should_implement_trait)]
pub fn as_mut(&mut self) -> &mut (dyn Any + Send + 'static) {
&mut *self.contents
}
}