use core::sync::atomic::{AtomicUsize, Ordering};
use alloc::{format, rc::Rc, vec::Vec};
use tinywasm_types::{FuncAddr, Function, Instruction, ModuleInstanceAddr, TypeAddr, ValType};
use crate::{
runtime::{self, DefaultRuntime},
Error, ModuleInstance, Result,
};
static STORE_ID: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
pub struct Store {
id: usize,
module_instances: Vec<ModuleInstance>,
module_instance_count: usize,
pub(crate) data: StoreData,
pub(crate) runtime: Runtime,
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum Runtime {
Default,
}
impl Store {
pub fn new() -> Self {
Self::default()
}
pub(crate) fn runtime(&self) -> runtime::DefaultRuntime {
match self.runtime {
Runtime::Default => DefaultRuntime::default(),
}
}
}
impl PartialEq for Store {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Default for Store {
fn default() -> Self {
let id = STORE_ID.fetch_add(1, Ordering::Relaxed);
Self {
id,
module_instances: Vec::new(),
module_instance_count: 0,
data: StoreData::default(),
runtime: Runtime::Default,
}
}
}
#[derive(Debug)]
pub struct FunctionInstance {
pub(crate) func: Function,
pub(crate) _module_instance: ModuleInstanceAddr, }
impl FunctionInstance {
pub(crate) fn _module_instance_addr(&self) -> ModuleInstanceAddr {
self._module_instance
}
pub(crate) fn locals(&self) -> &[ValType] {
&self.func.locals
}
pub(crate) fn instructions(&self) -> &[Instruction] {
&self.func.instructions
}
pub(crate) fn ty_addr(&self) -> TypeAddr {
self.func.ty
}
}
#[derive(Debug, Default)]
pub(crate) struct StoreData {
pub(crate) funcs: Vec<Rc<FunctionInstance>>,
}
impl Store {
pub fn id(&self) -> usize {
self.id
}
pub(crate) fn next_module_instance_idx(&self) -> ModuleInstanceAddr {
self.module_instance_count as ModuleInstanceAddr
}
pub(crate) fn add_instance(&mut self, instance: ModuleInstance) -> Result<()> {
self.module_instances.push(instance);
self.module_instance_count += 1;
Ok(())
}
pub(crate) fn add_funcs(&mut self, funcs: Vec<Function>, idx: ModuleInstanceAddr) -> Vec<FuncAddr> {
let mut func_addrs = Vec::with_capacity(funcs.len());
for func in funcs.into_iter() {
self.data.funcs.push(Rc::new(FunctionInstance {
func,
_module_instance: idx,
}));
func_addrs.push(idx as FuncAddr);
}
func_addrs
}
pub(crate) fn get_func(&self, addr: usize) -> Result<&Rc<FunctionInstance>> {
self.data
.funcs
.get(addr)
.ok_or_else(|| Error::Other(format!("function {} not found", addr)))
}
}