use std::{marker::PhantomData, num::NonZeroUsize};
use wasm_bindgen::JsValue;
use wasmer_types::StoreId;
use crate::js::vm::{function::VMFunctionEnvironment, global::VMGlobal};
use super::handle::InternalStoreHandle;
pub trait StoreObject: Sized {
fn list(store: &StoreObjects) -> &Vec<Self>;
fn list_mut(store: &mut StoreObjects) -> &mut Vec<Self>;
}
macro_rules! impl_store_object {
($($field:ident => $ty:ty,)*) => {
$(
impl StoreObject for $ty {
fn list(store: &StoreObjects) -> &Vec<Self> {
&store.$field
}
fn list_mut(store: &mut StoreObjects) -> &mut Vec<Self> {
&mut store.$field
}
}
)*
};
}
impl_store_object! {
globals => VMGlobal,
function_environments => VMFunctionEnvironment,
}
#[derive(Default, Debug)]
pub struct StoreObjects {
id: StoreId,
globals: Vec<VMGlobal>,
function_environments: Vec<VMFunctionEnvironment>,
}
impl StoreObjects {
pub fn id(&self) -> StoreId {
self.id
}
pub fn set_id(&mut self, id: StoreId) {
self.id = id;
}
pub fn get_2_mut<T: StoreObject>(
&mut self,
a: InternalStoreHandle<T>,
b: InternalStoreHandle<T>,
) -> (&mut T, &mut T) {
assert_ne!(a.index(), b.index());
let list = T::list_mut(self);
if a.index() < b.index() {
let (low, high) = list.split_at_mut(b.index());
(&mut low[a.index()], &mut high[0])
} else {
let (low, high) = list.split_at_mut(a.index());
(&mut high[0], &mut low[a.index()])
}
}
pub fn iter_globals(&self) -> core::slice::Iter<'_, VMGlobal> {
self.globals.iter()
}
pub fn as_u128_globals(&self) -> Vec<u128> {
self.iter_globals()
.map(|v| v.global.value().as_f64().unwrap() as u128)
.collect()
}
pub fn set_global_unchecked(&self, idx: usize, new_val: u128) {
assert!(idx < self.globals.len());
let g = &self.globals[idx].global;
let cur_val = g.value().as_f64().unwrap();
let new_val = new_val as f64;
if cur_val != new_val {
let new_value = JsValue::from(new_val);
g.set_value(&new_value);
}
}
}
impl crate::StoreObjects {
pub fn into_js(self) -> crate::backend::js::store::StoreObjects {
match self {
Self::Js(s) => s,
_ => panic!("Not a `js` store!"),
}
}
pub fn as_js(&self) -> &crate::backend::js::store::StoreObjects {
match self {
Self::Js(s) => s,
_ => panic!("Not a `js` store!"),
}
}
pub fn as_js_mut(&mut self) -> &mut crate::backend::js::store::StoreObjects {
match self {
Self::Js(s) => s,
_ => panic!("Not a `js` store!"),
}
}
}