#![allow(missing_docs)]
use crate::ast::FunctionArg;
use crate::IRecordType;
use crate::IType;
use crate::IValue;
use futures::future::BoxFuture;
use futures::FutureExt;
use std::sync::Arc;
pub use it_memory_traits::{Memory, MemoryAccessError, MemoryView};
use it_memory_traits::{MemoryReadable, MemoryWritable};
pub trait TypedIndex: Copy + Clone {
fn new(index: usize) -> Self;
fn index(&self) -> usize;
}
macro_rules! typed_index {
($type:ident) => {
#[derive(Copy, Clone)]
pub struct $type(usize);
impl TypedIndex for $type {
fn new(index: usize) -> Self {
Self(index)
}
fn index(&self) -> usize {
self.0
}
}
};
}
typed_index!(FunctionIndex);
typed_index!(LocalFunctionIndex);
typed_index!(ImportFunctionIndex);
pub trait LocalImportIndex {
type Local: TypedIndex;
type Import: TypedIndex;
}
impl LocalImportIndex for FunctionIndex {
type Local = LocalFunctionIndex;
type Import = ImportFunctionIndex;
}
pub trait Export: Send {
fn name(&self) -> &str;
fn inputs_cardinality(&self) -> usize;
fn outputs_cardinality(&self) -> usize;
fn arguments(&self) -> &[FunctionArg];
fn outputs(&self) -> &[IType];
fn call_async<'args>(
&'args self,
arguments: &'args [IValue],
) -> BoxFuture<'args, Result<Vec<IValue>, anyhow::Error>>;
}
pub trait LocalImport<Store: self::Store>: Send + Sync {
fn name(&self) -> &str;
fn inputs_cardinality(&self) -> usize;
fn outputs_cardinality(&self) -> usize;
fn arguments(&self) -> &[FunctionArg];
fn outputs(&self) -> &[IType];
fn call_async<'args>(
&'args self,
store: &'args mut <Store as self::Store>::ActualStore<'_>,
arguments: &'args [IValue],
) -> BoxFuture<Result<Vec<IValue>, anyhow::Error>>;
}
pub use it_memory_traits::Store;
pub trait Instance<E, LI, M, MV, S>: Send + Sync
where
E: Export,
LI: LocalImport<S>,
M: Memory<MV, S>,
MV: MemoryView<S>,
S: Store,
{
fn export(&self, export_name: &str) -> Option<&E>;
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&LI>;
fn memory(&self, index: usize) -> Option<&M>;
fn memory_view(&self, index: usize) -> Option<MV>;
fn wit_record_by_id(&self, index: u64) -> Option<&Arc<IRecordType>>;
}
impl<Store: self::Store> LocalImport<Store> for () {
fn name(&self) -> &str {
""
}
fn inputs_cardinality(&self) -> usize {
0
}
fn outputs_cardinality(&self) -> usize {
0
}
fn arguments(&self) -> &[FunctionArg] {
&[]
}
fn outputs(&self) -> &[IType] {
&[]
}
fn call_async(
&self,
_store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
_arguments: &[IValue],
) -> BoxFuture<Result<Vec<IValue>, anyhow::Error>> {
async { Err(anyhow::anyhow!("some error")) }.boxed()
}
}
impl Export for () {
fn name(&self) -> &str {
""
}
fn inputs_cardinality(&self) -> usize {
0
}
fn outputs_cardinality(&self) -> usize {
0
}
fn arguments(&self) -> &[FunctionArg] {
&[]
}
fn outputs(&self) -> &[IType] {
&[]
}
fn call_async(&self, _arguments: &[IValue]) -> BoxFuture<Result<Vec<IValue>, anyhow::Error>> {
async { Err(anyhow::anyhow!("some error")) }.boxed()
}
}
pub(crate) struct EmptyMemoryView;
impl<S: Store> MemoryWritable<S> for EmptyMemoryView {
fn write_byte(&self, _store: &mut <S as Store>::ActualStore<'_>, _offset: u32, _value: u8) {}
fn write_bytes(&self, _store: &mut <S as Store>::ActualStore<'_>, _offset: u32, _bytes: &[u8]) {
}
}
impl<S: Store> MemoryReadable<S> for EmptyMemoryView {
fn read_byte(&self, _store: &mut <S as Store>::ActualStore<'_>, _offset: u32) -> u8 {
0
}
fn read_array<const COUNT: usize>(
&self,
_store: &mut <S as Store>::ActualStore<'_>,
_offset: u32,
) -> [u8; COUNT] {
[0; COUNT]
}
fn read_vec(
&self,
_store: &mut <S as Store>::ActualStore<'_>,
_offset: u32,
_size: u32,
) -> Vec<u8> {
Vec::default()
}
}
impl<S: Store> MemoryView<S> for EmptyMemoryView {
fn check_bounds(
&self,
_store: &mut <S as Store>::ActualStore<'_>,
offset: u32,
size: u32,
) -> Result<(), MemoryAccessError> {
Err(MemoryAccessError::OutOfBounds {
size,
offset,
memory_size: 0,
})
}
}
impl<S: Store> Memory<EmptyMemoryView, S> for () {
fn view(&self) -> EmptyMemoryView {
EmptyMemoryView
}
}
impl<E, LI, M, MV, S> Instance<E, LI, M, MV, S> for ()
where
E: Export,
LI: LocalImport<S>,
M: Memory<MV, S>,
MV: MemoryView<S>,
S: Store,
{
fn export(&self, _export_name: &str) -> Option<&E> {
None
}
fn memory(&self, _: usize) -> Option<&M> {
None
}
fn memory_view(&self, _index: usize) -> Option<MV> {
None
}
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, _index: I) -> Option<&LI> {
None
}
fn wit_record_by_id(&self, _index: u64) -> Option<&Arc<IRecordType>> {
None
}
}