mirror of
https://github.com/fluencelabs/interface-types
synced 2025-04-24 23:32:13 +00:00
feat(interface-types) Introduce the wasm::structures::MemoryView
trait.
This commit is contained in:
parent
a27782ac66
commit
f206ccd55f
@ -1,7 +1,7 @@
|
||||
use crate::interpreter::Instruction;
|
||||
use std::str;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum InterfaceType {
|
||||
Int,
|
||||
Float,
|
||||
|
@ -14,9 +14,9 @@ pub(crate) use write_utf8::write_utf8;
|
||||
pub(crate) mod tests {
|
||||
use crate::interpreter::wasm::{
|
||||
self,
|
||||
values::{InterfaceType, InterfaceValue, ValueType},
|
||||
values::{InterfaceType, InterfaceValue},
|
||||
};
|
||||
use std::{cell::Cell, collections::HashMap, convert::TryInto};
|
||||
use std::{cell::Cell, collections::HashMap, convert::TryInto, ops::Deref, rc::Rc};
|
||||
|
||||
pub(crate) struct Export {
|
||||
pub(crate) inputs: Vec<InterfaceType>,
|
||||
@ -74,24 +74,35 @@ pub(crate) mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub(crate) struct MemoryView(Rc<Vec<Cell<u8>>>);
|
||||
|
||||
impl wasm::structures::MemoryView for MemoryView {}
|
||||
|
||||
impl Deref for MemoryView {
|
||||
type Target = [Cell<u8>];
|
||||
|
||||
fn deref(&self) -> &[Cell<u8>] {
|
||||
self.0.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct Memory {
|
||||
pub(crate) data: Vec<Cell<u8>>,
|
||||
pub(crate) view: MemoryView,
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
pub(crate) fn new(data: Vec<Cell<u8>>) -> Self {
|
||||
Self { data }
|
||||
Self {
|
||||
view: MemoryView(Rc::new(data)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl wasm::structures::Memory for Memory {
|
||||
fn view<V: ValueType>(&self) -> &[Cell<V>] {
|
||||
use std::slice;
|
||||
|
||||
let slice = self.data.as_slice();
|
||||
|
||||
unsafe { slice::from_raw_parts(slice.as_ptr() as *const Cell<V>, slice.len()) }
|
||||
impl wasm::structures::Memory<MemoryView> for Memory {
|
||||
fn view(&self) -> MemoryView {
|
||||
self.view.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +169,7 @@ pub(crate) mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl wasm::structures::Instance<Export, LocalImport, Memory> for Instance {
|
||||
impl wasm::structures::Instance<Export, LocalImport, Memory, MemoryView> for Instance {
|
||||
fn export(&self, export_name: &str) -> Option<&Export> {
|
||||
self.exports.get(export_name)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ executable_instruction!(
|
||||
Some(memory) => {
|
||||
let length = i32::try_from(&inputs[0])? as usize;
|
||||
let pointer = i32::try_from(&inputs[1])? as usize;
|
||||
let memory_view = memory.view::<u8>();
|
||||
let memory_view = memory.view();
|
||||
|
||||
if memory_view.len() < pointer + length {
|
||||
return Err(format!(
|
||||
|
@ -20,7 +20,7 @@ executable_instruction!(
|
||||
match runtime.wasm_instance.memory(0) {
|
||||
Some(memory) => match runtime.stack.pop1() {
|
||||
Some(string) => {
|
||||
let memory_view = memory.view::<u8>();
|
||||
let memory_view = memory.view();
|
||||
|
||||
let string: String = (&string).try_into()?;
|
||||
let string_bytes = string.as_bytes();
|
||||
|
@ -8,45 +8,50 @@ use stack::Stack;
|
||||
use std::{convert::TryFrom, marker::PhantomData};
|
||||
use wasm::values::InterfaceValue;
|
||||
|
||||
pub(crate) struct Runtime<'invocation, 'instance, Instance, Export, LocalImport, Memory>
|
||||
pub(crate) struct Runtime<'invocation, 'instance, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export + 'instance,
|
||||
LocalImport: wasm::structures::LocalImport + 'instance,
|
||||
Memory: wasm::structures::Memory + 'instance,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory> + 'instance,
|
||||
Memory: wasm::structures::Memory<MemoryView> + 'instance,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView> + 'instance,
|
||||
{
|
||||
invocation_inputs: &'invocation [InterfaceValue],
|
||||
stack: Stack<InterfaceValue>,
|
||||
wasm_instance: &'instance Instance,
|
||||
_wasm_exports: PhantomData<Export>,
|
||||
_wasm_locals_or_imports: PhantomData<LocalImport>,
|
||||
_wasm_memories: PhantomData<Memory>,
|
||||
_phantom: PhantomData<(Export, LocalImport, Memory, MemoryView)>,
|
||||
}
|
||||
|
||||
pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory> =
|
||||
Box<dyn Fn(&mut Runtime<Instance, Export, LocalImport, Memory>) -> Result<(), String>>;
|
||||
pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView> = Box<
|
||||
dyn Fn(&mut Runtime<Instance, Export, LocalImport, Memory, MemoryView>) -> Result<(), String>,
|
||||
>;
|
||||
|
||||
pub struct Interpreter<Instance, Export, LocalImport, Memory>
|
||||
pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export,
|
||||
LocalImport: wasm::structures::LocalImport,
|
||||
Memory: wasm::structures::Memory,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory>,
|
||||
Memory: wasm::structures::Memory<MemoryView>,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
executable_instructions: Vec<ExecutableInstruction<Instance, Export, LocalImport, Memory>>,
|
||||
executable_instructions:
|
||||
Vec<ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>>,
|
||||
}
|
||||
|
||||
impl<Instance, Export, LocalImport, Memory> Interpreter<Instance, Export, LocalImport, Memory>
|
||||
impl<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export,
|
||||
LocalImport: wasm::structures::LocalImport,
|
||||
Memory: wasm::structures::Memory,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory>,
|
||||
Memory: wasm::structures::Memory<MemoryView>,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
fn iter(
|
||||
&self,
|
||||
) -> impl Iterator<Item = &ExecutableInstruction<Instance, Export, LocalImport, Memory>> + '_
|
||||
{
|
||||
) -> impl Iterator<
|
||||
Item = &ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>,
|
||||
> + '_ {
|
||||
self.executable_instructions.iter()
|
||||
}
|
||||
|
||||
@ -59,9 +64,7 @@ where
|
||||
invocation_inputs,
|
||||
stack: Stack::new(),
|
||||
wasm_instance,
|
||||
_wasm_exports: PhantomData,
|
||||
_wasm_locals_or_imports: PhantomData,
|
||||
_wasm_memories: PhantomData,
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
|
||||
for executable_instruction in self.iter() {
|
||||
@ -75,13 +78,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'binary_input, Instance, Export, LocalImport, Memory> TryFrom<&Vec<Instruction<'binary_input>>>
|
||||
for Interpreter<Instance, Export, LocalImport, Memory>
|
||||
impl<'binary_input, Instance, Export, LocalImport, Memory, MemoryView>
|
||||
TryFrom<&Vec<Instruction<'binary_input>>>
|
||||
for Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export,
|
||||
LocalImport: wasm::structures::LocalImport,
|
||||
Memory: wasm::structures::Memory,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory>,
|
||||
Memory: wasm::structures::Memory<MemoryView>,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
type Error = String;
|
||||
|
||||
@ -118,7 +123,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Instruction, Interpreter};
|
||||
use super::{wasm::structures::EmptyMemoryView, Instruction, Interpreter};
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[test]
|
||||
@ -130,7 +135,8 @@ mod tests {
|
||||
Instruction::ReadUtf8,
|
||||
Instruction::Call { function_index: 7 },
|
||||
];
|
||||
let interpreter: Interpreter<(), (), (), ()> = (&instructions).try_into().unwrap();
|
||||
let interpreter: Interpreter<(), (), (), (), EmptyMemoryView> =
|
||||
(&instructions).try_into().unwrap();
|
||||
|
||||
assert_eq!(interpreter.executable_instructions.len(), 5);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::values::{InterfaceType, InterfaceValue, ValueType};
|
||||
use std::cell::Cell;
|
||||
use super::values::{InterfaceType, InterfaceValue};
|
||||
use std::{cell::Cell, ops::Deref};
|
||||
|
||||
pub trait TypedIndex: Copy + Clone {
|
||||
fn new(index: usize) -> Self;
|
||||
@ -53,15 +53,21 @@ pub trait LocalImport {
|
||||
fn call(&self, arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()>;
|
||||
}
|
||||
|
||||
pub trait Memory {
|
||||
fn view<V: ValueType>(&self) -> &[Cell<V>];
|
||||
pub trait MemoryView: Deref<Target = [Cell<u8>]> {}
|
||||
|
||||
pub trait Memory<View>
|
||||
where
|
||||
View: MemoryView,
|
||||
{
|
||||
fn view(&self) -> View;
|
||||
}
|
||||
|
||||
pub trait Instance<E, LI, M>
|
||||
pub trait Instance<E, LI, M, MV>
|
||||
where
|
||||
E: Export,
|
||||
LI: LocalImport,
|
||||
M: Memory,
|
||||
M: Memory<MV>,
|
||||
MV: MemoryView,
|
||||
{
|
||||
fn export(&self, export_name: &str) -> Option<&E>;
|
||||
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&LI>;
|
||||
@ -112,17 +118,30 @@ impl LocalImport for () {
|
||||
}
|
||||
}
|
||||
|
||||
impl Memory for () {
|
||||
fn view<V: ValueType>(&self) -> &[Cell<V>] {
|
||||
pub(crate) struct EmptyMemoryView;
|
||||
|
||||
impl MemoryView for EmptyMemoryView {}
|
||||
|
||||
impl Deref for EmptyMemoryView {
|
||||
type Target = [Cell<u8>];
|
||||
|
||||
fn deref(&self) -> &[Cell<u8>] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, LI, M> Instance<E, LI, M> for ()
|
||||
impl Memory<EmptyMemoryView> for () {
|
||||
fn view(&self) -> EmptyMemoryView {
|
||||
EmptyMemoryView
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, LI, M, MV> Instance<E, LI, M, MV> for ()
|
||||
where
|
||||
E: Export,
|
||||
LI: LocalImport,
|
||||
M: Memory,
|
||||
M: Memory<MV>,
|
||||
MV: MemoryView,
|
||||
{
|
||||
fn export(&self, _export_name: &str) -> Option<&E> {
|
||||
None
|
||||
|
@ -63,23 +63,3 @@ from_x_for_interface_value!(i32, I32);
|
||||
from_x_for_interface_value!(i64, I64);
|
||||
from_x_for_interface_value!(f32, F32);
|
||||
from_x_for_interface_value!(f64, F64);
|
||||
|
||||
pub trait ValueType: Copy
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
}
|
||||
|
||||
macro_rules! value_type {
|
||||
($native_type:ty) => {
|
||||
impl ValueType for $native_type {}
|
||||
};
|
||||
|
||||
($($native_type:ty),*) => {
|
||||
$(
|
||||
value_type!($native_type);
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
value_type!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
|
||||
|
@ -28,14 +28,15 @@ macro_rules! executable_instruction {
|
||||
($name:ident ( $($argument_name:ident: $argument_type:ty),* ) -> _ $implementation:block ) => {
|
||||
use crate::interpreter::{ExecutableInstruction, wasm, stack::Stackable};
|
||||
|
||||
pub(crate) fn $name<Instance, Export, LocalImport, Memory>(
|
||||
pub(crate) fn $name<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
$($argument_name: $argument_type),*
|
||||
) -> ExecutableInstruction<Instance, Export, LocalImport, Memory>
|
||||
) -> ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export,
|
||||
LocalImport: wasm::structures::LocalImport,
|
||||
Memory: wasm::structures::Memory,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory>,
|
||||
Memory: wasm::structures::Memory<MemoryView>,
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
Box::new($implementation)
|
||||
}
|
||||
@ -56,14 +57,14 @@ macro_rules! test_executable_instruction {
|
||||
#[allow(non_snake_case, unused)]
|
||||
fn $test_name() {
|
||||
use crate::interpreter::{
|
||||
instructions::tests::{Export, Instance, LocalImport, Memory},
|
||||
instructions::tests::{Export, Instance, LocalImport, Memory, MemoryView},
|
||||
stack::Stackable,
|
||||
wasm::values::{InterfaceType, InterfaceValue},
|
||||
Instruction, Interpreter,
|
||||
};
|
||||
use std::{cell::Cell, collections::HashMap, convert::TryInto};
|
||||
|
||||
let interpreter: Interpreter<Instance, Export, LocalImport, Memory> =
|
||||
let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> =
|
||||
(&vec![$($instructions),*]).try_into().unwrap();
|
||||
|
||||
let invocation_inputs = vec![$($invocation_inputs),*];
|
||||
@ -90,14 +91,14 @@ macro_rules! test_executable_instruction {
|
||||
#[allow(non_snake_case, unused)]
|
||||
fn $test_name() {
|
||||
use crate::interpreter::{
|
||||
instructions::tests::{Export, Instance, LocalImport, Memory},
|
||||
instructions::tests::{Export, Instance, LocalImport, Memory, MemoryView},
|
||||
stack::Stackable,
|
||||
wasm::values::{InterfaceType, InterfaceValue},
|
||||
Instruction, Interpreter,
|
||||
};
|
||||
use std::{cell::Cell, collections::HashMap, convert::TryInto};
|
||||
|
||||
let interpreter: Interpreter<Instance, Export, LocalImport, Memory> =
|
||||
let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> =
|
||||
(&vec![$($instructions),*]).try_into().unwrap();
|
||||
|
||||
let invocation_inputs = vec![$($invocation_inputs),*];
|
||||
|
Loading…
x
Reference in New Issue
Block a user