mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 15:20:20 +00:00
commit
1ccedeba65
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -195,7 +195,7 @@ checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
|
||||
|
||||
[[package]]
|
||||
name = "wasmer-interface-types-fl"
|
||||
version = "0.17.7"
|
||||
version = "0.17.6"
|
||||
dependencies = [
|
||||
"log",
|
||||
"nom",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasmer-interface-types-fl"
|
||||
version = "0.17.7"
|
||||
version = "0.17.6"
|
||||
description = "WebAssembly Interface Types library for Wasmer"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
|
@ -118,7 +118,11 @@ fn ty<'input, E: ParseError<&'input [u8]>>(
|
||||
0x08 => InterfaceType::F32,
|
||||
0x09 => InterfaceType::F64,
|
||||
0x0a => InterfaceType::String,
|
||||
0x36 => InterfaceType::ByteArray,
|
||||
0x36 => {
|
||||
consume!((input, array_value_type) = ty(input)?);
|
||||
|
||||
InterfaceType::Array(Box::new(array_value_type))
|
||||
}
|
||||
0x0b => InterfaceType::Anyref,
|
||||
0x0c => InterfaceType::I32,
|
||||
0x0d => InterfaceType::I64,
|
||||
@ -288,11 +292,19 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
|
||||
0x23 => (input, Instruction::StringLowerMemory),
|
||||
0x24 => (input, Instruction::StringSize),
|
||||
|
||||
0x37 => (input, Instruction::ByteArrayLiftMemory),
|
||||
0x38 => (input, Instruction::ByteArrayLowerMemory),
|
||||
0x39 => (input, Instruction::ByteArraySize),
|
||||
0x37 => {
|
||||
consume!((input, value_type) = ty(input)?);
|
||||
|
||||
(input, Instruction::ArrayLiftMemory { value_type })
|
||||
}
|
||||
0x38 => {
|
||||
consume!((input, value_type) = ty(input)?);
|
||||
|
||||
(input, Instruction::ArrayLowerMemory { value_type })
|
||||
}
|
||||
/*
|
||||
0x39 => (input, Instruction::ArraySize),
|
||||
|
||||
0x25 => {
|
||||
consume!((input, argument_0) = uleb(input)?);
|
||||
|
||||
@ -315,22 +327,22 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
|
||||
}
|
||||
*/
|
||||
0x3A => {
|
||||
consume!((input, argument_0) = uleb(input)?);
|
||||
consume!((input, record_type_id) = uleb(input)?);
|
||||
|
||||
(
|
||||
input,
|
||||
Instruction::RecordLiftMemory {
|
||||
record_type_id: argument_0 as u32,
|
||||
record_type_id: record_type_id as u32,
|
||||
},
|
||||
)
|
||||
}
|
||||
0x3B => {
|
||||
consume!((input, argument_0) = uleb(input)?);
|
||||
consume!((input, record_type_id) = uleb(input)?);
|
||||
|
||||
(
|
||||
input,
|
||||
Instruction::RecordLowerMemory {
|
||||
record_type_id: argument_0 as u32,
|
||||
record_type_id: record_type_id as u32,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ mod keyword {
|
||||
custom_keyword!(u32);
|
||||
custom_keyword!(u64);
|
||||
custom_keyword!(string);
|
||||
custom_keyword!(byte_array);
|
||||
custom_keyword!(Array);
|
||||
|
||||
// Instructions.
|
||||
custom_keyword!(argument_get = "arg.get");
|
||||
@ -71,9 +71,9 @@ mod keyword {
|
||||
custom_keyword!(string_lift_memory = "string.lift_memory");
|
||||
custom_keyword!(string_lower_memory = "string.lower_memory");
|
||||
custom_keyword!(string_size = "string.size");
|
||||
custom_keyword!(byte_array_lift_memory = "byte_array.lift_memory");
|
||||
custom_keyword!(byte_array_lower_memory = "byte_array.lower_memory");
|
||||
custom_keyword!(byte_array_size = "byte_array.size");
|
||||
custom_keyword!(array_lift_memory = "array.lift_memory");
|
||||
custom_keyword!(array_lower_memory = "array.lower_memory");
|
||||
custom_keyword!(array_size = "array.size");
|
||||
custom_keyword!(record_lift = "record.lift");
|
||||
custom_keyword!(record_lower = "record.lower");
|
||||
custom_keyword!(record_lift_memory = "record.lift_memory");
|
||||
@ -130,10 +130,10 @@ impl Parse<'_> for InterfaceType {
|
||||
parser.parse::<keyword::string>()?;
|
||||
|
||||
Ok(InterfaceType::String)
|
||||
} else if lookahead.peek::<keyword::byte_array>() {
|
||||
parser.parse::<keyword::byte_array>()?;
|
||||
} else if lookahead.peek::<keyword::Array>() {
|
||||
parser.parse::<keyword::Array>()?;
|
||||
|
||||
Ok(InterfaceType::ByteArray)
|
||||
Ok(InterfaceType::Array(Box::new(parser.parse()?)))
|
||||
} else if lookahead.peek::<keyword::anyref>() {
|
||||
parser.parse::<keyword::anyref>()?;
|
||||
|
||||
@ -352,18 +352,18 @@ impl<'a> Parse<'a> for Instruction {
|
||||
parser.parse::<keyword::string_size>()?;
|
||||
|
||||
Ok(Instruction::StringSize)
|
||||
} else if lookahead.peek::<keyword::byte_array_lift_memory>() {
|
||||
parser.parse::<keyword::byte_array_lift_memory>()?;
|
||||
} else if lookahead.peek::<keyword::array_lift_memory>() {
|
||||
parser.parse::<keyword::array_lift_memory>()?;
|
||||
|
||||
Ok(Instruction::ByteArrayLiftMemory)
|
||||
} else if lookahead.peek::<keyword::byte_array_lower_memory>() {
|
||||
parser.parse::<keyword::byte_array_lower_memory>()?;
|
||||
Ok(Instruction::ArrayLiftMemory {
|
||||
value_type: parser.parse()?,
|
||||
})
|
||||
} else if lookahead.peek::<keyword::array_lower_memory>() {
|
||||
parser.parse::<keyword::array_lower_memory>()?;
|
||||
|
||||
Ok(Instruction::ByteArrayLowerMemory)
|
||||
} else if lookahead.peek::<keyword::byte_array_size>() {
|
||||
parser.parse::<keyword::byte_array_size>()?;
|
||||
|
||||
Ok(Instruction::ByteArraySize)
|
||||
Ok(Instruction::ArrayLowerMemory {
|
||||
value_type: parser.parse()?,
|
||||
})
|
||||
}
|
||||
/*
|
||||
else if lookahead.peek::<keyword::record_lift>() {
|
||||
|
@ -123,7 +123,10 @@ where
|
||||
InterfaceType::F32 => 0x08_u8.to_bytes(writer),
|
||||
InterfaceType::F64 => 0x09_u8.to_bytes(writer),
|
||||
InterfaceType::String => 0x0a_u8.to_bytes(writer),
|
||||
InterfaceType::ByteArray => 0x36_u8.to_bytes(writer),
|
||||
InterfaceType::Array(ty) => {
|
||||
0x36_u8.to_bytes(writer)?;
|
||||
ty.to_bytes(writer)
|
||||
}
|
||||
InterfaceType::Anyref => 0x0b_u8.to_bytes(writer),
|
||||
InterfaceType::I32 => 0x0c_u8.to_bytes(writer),
|
||||
InterfaceType::I64 => 0x0d_u8.to_bytes(writer),
|
||||
@ -378,10 +381,16 @@ where
|
||||
Instruction::StringLowerMemory => 0x23_u8.to_bytes(writer)?,
|
||||
Instruction::StringSize => 0x24_u8.to_bytes(writer)?,
|
||||
|
||||
Instruction::ByteArrayLiftMemory => 0x37_u8.to_bytes(writer)?,
|
||||
Instruction::ByteArrayLowerMemory => 0x38_u8.to_bytes(writer)?,
|
||||
Instruction::ByteArraySize => 0x39_u8.to_bytes(writer)?,
|
||||
Instruction::ArrayLiftMemory { value_type } => {
|
||||
0x37_u8.to_bytes(writer)?;
|
||||
value_type.to_bytes(writer)?
|
||||
}
|
||||
Instruction::ArrayLowerMemory { value_type } => {
|
||||
0x38_u8.to_bytes(writer)?;
|
||||
value_type.to_bytes(writer)?
|
||||
}
|
||||
/*
|
||||
Instruction::ArraySize => 0x39_u8.to_bytes(writer)?,
|
||||
Instruction::RecordLift { type_index } => {
|
||||
0x25_u8.to_bytes(writer)?;
|
||||
(*type_index as u64).to_bytes(writer)?
|
||||
|
@ -73,7 +73,7 @@ impl ToString for &InterfaceType {
|
||||
InterfaceType::F32 => "f32".to_string(),
|
||||
InterfaceType::F64 => "f64".to_string(),
|
||||
InterfaceType::String => "string".to_string(),
|
||||
InterfaceType::ByteArray => "byte_array".to_string(),
|
||||
InterfaceType::Array(ty) => format!("Array<{:?}>", ty),
|
||||
InterfaceType::Anyref => "anyref".to_string(),
|
||||
InterfaceType::I32 => "i32".to_string(),
|
||||
InterfaceType::I64 => "i64".to_string(),
|
||||
@ -144,10 +144,14 @@ impl ToString for &Instruction {
|
||||
Instruction::StringLiftMemory => "string.lift_memory".into(),
|
||||
Instruction::StringLowerMemory => "string.lower_memory".into(),
|
||||
Instruction::StringSize => "string.size".into(),
|
||||
Instruction::ByteArrayLiftMemory => "byte_array.lift_memory".into(),
|
||||
Instruction::ByteArrayLowerMemory => "byte_array.lower_memory".into(),
|
||||
Instruction::ByteArraySize => "byte_array.size".into(),
|
||||
Instruction::ArrayLiftMemory { value_type } => {
|
||||
format!("array.lift_memory {:?}", value_type)
|
||||
}
|
||||
Instruction::ArrayLowerMemory { value_type } => {
|
||||
format!("array.lower_memory {:?}", value_type)
|
||||
}
|
||||
/*
|
||||
Instruction::ArraySize => "byte_array.size".into(),
|
||||
Instruction::RecordLift { type_index } => format!("record.lift {}", type_index),
|
||||
Instruction::RecordLower { type_index } => format!("record.lower {}", type_index),
|
||||
*/
|
||||
|
@ -170,6 +170,9 @@ pub enum InstructionErrorKind {
|
||||
record_type_id: u64,
|
||||
},
|
||||
|
||||
/// Corrupted array's been popped from the stack.
|
||||
CorruptedArray(String),
|
||||
|
||||
/// Corrupted record's been popped from the stack.
|
||||
CorruptedRecord(String),
|
||||
|
||||
@ -278,6 +281,12 @@ impl Display for InstructionErrorKind {
|
||||
type_name
|
||||
),
|
||||
|
||||
Self::CorruptedArray(err) => write!(
|
||||
formatter,
|
||||
"{}",
|
||||
err
|
||||
),
|
||||
|
||||
Self::CorruptedRecord(err) => write!(
|
||||
formatter,
|
||||
"{}",
|
||||
|
@ -10,7 +10,7 @@ executable_instruction!(
|
||||
|
||||
if (index as usize) >= invocation_inputs.len() {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvocationInputIsMissing { index },
|
||||
));
|
||||
}
|
||||
|
397
src/interpreter/instructions/arrays.rs
Normal file
397
src/interpreter/instructions/arrays.rs
Normal file
@ -0,0 +1,397 @@
|
||||
use super::deallocate;
|
||||
use super::read_from_instance_mem;
|
||||
use super::write_to_instance_mem;
|
||||
|
||||
use crate::interpreter::instructions::to_native;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::Instruction,
|
||||
types::InterfaceType,
|
||||
values::InterfaceValue,
|
||||
};
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub(super) fn array_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
value_type: &InterfaceType,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
instruction: Instruction,
|
||||
) -> Result<Vec<InterfaceValue>, InstructionError>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
LocalImport: crate::interpreter::wasm::structures::LocalImport,
|
||||
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
|
||||
MemoryView: crate::interpreter::wasm::structures::MemoryView,
|
||||
Instance: crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>
|
||||
+ 'instance,
|
||||
{
|
||||
use safe_transmute::guard::AllOrNothingGuard;
|
||||
use safe_transmute::transmute_many;
|
||||
use safe_transmute::transmute_vec;
|
||||
|
||||
if size == 0 {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let data = read_from_instance_mem(instance, instruction.clone(), offset, size)?;
|
||||
|
||||
let result_array = match value_type {
|
||||
InterfaceType::S8 => {
|
||||
let data = transmute_vec::<u8, i8>(data).unwrap();
|
||||
data.into_iter().map(InterfaceValue::S8).collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::S16 => {
|
||||
let data = transmute_many::<i16, AllOrNothingGuard>(&data).unwrap();
|
||||
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::S16(*v))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::S32 => {
|
||||
let data = transmute_many::<i32, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::S32(*v))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::S64 => {
|
||||
let data = transmute_many::<i64, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::S64(*v))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::I32 => {
|
||||
let data = transmute_many::<i32, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::I32(*v))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::I64 => {
|
||||
let data = transmute_many::<i64, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::S64(*v))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::U8 => data.into_iter().map(InterfaceValue::U8).collect::<Vec<_>>(),
|
||||
InterfaceType::U16 => {
|
||||
let data = transmute_many::<u16, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::U16(*v))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::U32 => {
|
||||
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::U32(*v))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::U64 => {
|
||||
let data = transmute_many::<u64, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::U64(*v))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::F32 => {
|
||||
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::F32(f32::from_bits(*v)))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::F64 => {
|
||||
let data = transmute_many::<u64, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::F64(f64::from_bits(*v)))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::Anyref => unimplemented!(),
|
||||
InterfaceType::String => {
|
||||
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
|
||||
|
||||
if data.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let mut result = Vec::with_capacity(data.len() / 2);
|
||||
let mut data = data.iter();
|
||||
|
||||
while let Some(string_offset) = data.next() {
|
||||
let string_size = data.next().ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::CorruptedArray(String::from(
|
||||
"serialized array must contain even count of elements",
|
||||
)),
|
||||
)
|
||||
})?;
|
||||
|
||||
let string_mem = read_from_instance_mem(
|
||||
instance,
|
||||
instruction.clone(),
|
||||
*string_offset as _,
|
||||
*string_size as _,
|
||||
)?;
|
||||
|
||||
// TODO: check
|
||||
let string = String::from_utf8(string_mem).unwrap();
|
||||
result.push(InterfaceValue::String(string));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
InterfaceType::Array(ty) => {
|
||||
let data = transmute_many::<
|
||||
u32,
|
||||
AllOrNothingGuard,
|
||||
>(&data)
|
||||
.unwrap();
|
||||
|
||||
if data.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let mut result = Vec::with_capacity(data.len() / 2);
|
||||
let mut data = data.iter();
|
||||
|
||||
while let Some(array_offset) = data.next() {
|
||||
let array_size = data.next().ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::CorruptedArray(String::from(
|
||||
"serialized array must contain even count of elements",
|
||||
)),
|
||||
)
|
||||
})?;
|
||||
|
||||
let value = array_lift_memory_(
|
||||
instance,
|
||||
&*ty,
|
||||
*array_offset as _,
|
||||
*array_size as _,
|
||||
instruction.clone(),
|
||||
)?;
|
||||
|
||||
result.push(InterfaceValue::Array(value));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
InterfaceType::Record(record_type_id) => {
|
||||
let record_type = instance.wit_record_by_id(*record_type_id).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::RecordTypeByNameIsMissing {
|
||||
record_type_id: *record_type_id,
|
||||
},
|
||||
)
|
||||
})?;
|
||||
|
||||
let data = transmute_many::<
|
||||
u32,
|
||||
AllOrNothingGuard,
|
||||
>(&data)
|
||||
.unwrap();
|
||||
|
||||
let mut result = Vec::with_capacity(data.len());
|
||||
|
||||
for record_offset in data {
|
||||
result.push(super::record_lift_memory_(
|
||||
instance,
|
||||
record_type,
|
||||
*record_offset as _,
|
||||
instruction.clone(),
|
||||
)?);
|
||||
}
|
||||
result
|
||||
}
|
||||
};
|
||||
|
||||
deallocate(instance, instruction, offset as _, size as _)?;
|
||||
|
||||
Ok(result_array)
|
||||
}
|
||||
|
||||
pub(crate) fn array_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instruction: Instruction,
|
||||
value_type: InterfaceType,
|
||||
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
LocalImport: crate::interpreter::wasm::structures::LocalImport,
|
||||
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
|
||||
MemoryView: crate::interpreter::wasm::structures::MemoryView,
|
||||
Instance:
|
||||
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
#[allow(unused_imports)]
|
||||
use crate::interpreter::stack::Stackable;
|
||||
Box::new({
|
||||
move |runtime| -> _ {
|
||||
let inputs = runtime.stack.pop(2).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)
|
||||
})?;
|
||||
|
||||
let offset: usize = to_native::<i32>(&inputs[0], instruction.clone())?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "offset").into())
|
||||
.map_err(|k| InstructionError::new(instruction.clone(), k))?;
|
||||
|
||||
let size: usize = to_native::<i32>(&inputs[1], instruction.clone())?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "size").into())
|
||||
.map_err(|k| InstructionError::new(instruction.clone(), k))?;
|
||||
|
||||
log::trace!(
|
||||
"array.lift_memory: lifting memory for value type: {:?}, popped offset {}, size {}",
|
||||
value_type,
|
||||
offset,
|
||||
size
|
||||
);
|
||||
|
||||
let instance = &mut runtime.wasm_instance;
|
||||
let array = array_lift_memory_(
|
||||
*instance,
|
||||
&value_type,
|
||||
offset as _,
|
||||
size as _,
|
||||
instruction.clone(),
|
||||
)?;
|
||||
|
||||
log::trace!("array.lift_memory: pushing {:?} on the stack", array);
|
||||
runtime.stack.push(InterfaceValue::Array(array));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn array_lower_memory_<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &mut Instance,
|
||||
instruction: Instruction,
|
||||
array_values: Vec<InterfaceValue>,
|
||||
) -> Result<(usize, usize), InstructionError>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
LocalImport: crate::interpreter::wasm::structures::LocalImport,
|
||||
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
|
||||
MemoryView: crate::interpreter::wasm::structures::MemoryView,
|
||||
Instance:
|
||||
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
let mut result: Vec<u64> = Vec::with_capacity(array_values.len());
|
||||
|
||||
// here it's known that all interface values have the same type
|
||||
for value in array_values {
|
||||
match value {
|
||||
InterfaceValue::S8(value) => result.push(value as _),
|
||||
InterfaceValue::S16(value) => result.push(value as _),
|
||||
InterfaceValue::S32(value) => result.push(value as _),
|
||||
InterfaceValue::S64(value) => result.push(value as _),
|
||||
InterfaceValue::U8(value) => result.push(value as _),
|
||||
InterfaceValue::U16(value) => result.push(value as _),
|
||||
InterfaceValue::U32(value) => result.push(value as _),
|
||||
InterfaceValue::U64(value) => result.push(value as _),
|
||||
InterfaceValue::I32(value) => result.push(value as _),
|
||||
InterfaceValue::I64(value) => result.push(value as _),
|
||||
InterfaceValue::F32(value) => result.push(value as _),
|
||||
InterfaceValue::F64(value) => result.push(value.to_bits()),
|
||||
InterfaceValue::String(value) => {
|
||||
let string_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
result.push(string_pointer as _);
|
||||
result.push(value.len() as _);
|
||||
}
|
||||
|
||||
InterfaceValue::Array(values) => {
|
||||
let (array_offset, array_size) = if !values.is_empty() {
|
||||
array_lower_memory_(instance, instruction.clone(), values)?
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
||||
result.push(array_offset as _);
|
||||
result.push(array_size as _);
|
||||
}
|
||||
|
||||
InterfaceValue::Record(values) => {
|
||||
let record_offset =
|
||||
super::record_lower_memory_(instance, instruction.clone(), values)?;
|
||||
result.push(record_offset as _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result = safe_transmute::transmute_to_bytes::<u64>(&result);
|
||||
let result_pointer = write_to_instance_mem(instance, instruction, &result)?;
|
||||
|
||||
Ok((result_pointer as _, result.len() as _))
|
||||
}
|
||||
|
||||
pub(crate) fn array_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instruction: Instruction,
|
||||
value_type: InterfaceType,
|
||||
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
LocalImport: crate::interpreter::wasm::structures::LocalImport,
|
||||
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
|
||||
MemoryView: crate::interpreter::wasm::structures::MemoryView,
|
||||
Instance:
|
||||
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
#[allow(unused_imports)]
|
||||
use crate::interpreter::stack::Stackable;
|
||||
Box::new({
|
||||
move |runtime| -> _ {
|
||||
let instance = &mut runtime.wasm_instance;
|
||||
let stack_value = runtime.stack.pop1().ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)
|
||||
})?;
|
||||
|
||||
match stack_value {
|
||||
InterfaceValue::Array(values) => {
|
||||
log::trace!("array.lower_memory: obtained {:?} values on the stack for interface type {:?}", values, value_type);
|
||||
|
||||
for value in values.iter() {
|
||||
super::is_value_compatible_to_type(
|
||||
&**instance,
|
||||
&value_type,
|
||||
&value,
|
||||
instruction.clone(),
|
||||
)?;
|
||||
}
|
||||
|
||||
let (offset, size) =
|
||||
array_lower_memory_(*instance, instruction.clone(), values)?;
|
||||
|
||||
log::trace!(
|
||||
"array.lower_memory: pushing {}, {} on the stack",
|
||||
offset,
|
||||
size
|
||||
);
|
||||
runtime.stack.push(InterfaceValue::I32(offset as _));
|
||||
runtime.stack.push(InterfaceValue::I32(size as _));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::Array(Box::new(value_type.clone())),
|
||||
received_value: stack_value.clone(),
|
||||
},
|
||||
)),
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
use super::to_native;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::Instruction,
|
||||
types::InterfaceType,
|
||||
values::InterfaceValue,
|
||||
};
|
||||
use std::{cell::Cell, convert::TryInto};
|
||||
|
||||
executable_instruction!(
|
||||
byte_array_lift_memory(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
let inputs = runtime.stack.pop(2).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 2 },
|
||||
)
|
||||
})?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
let memory = runtime
|
||||
.wasm_instance
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?;
|
||||
|
||||
let pointer: usize = to_native::<i32>(&inputs[0], instruction)?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "pointer").into())
|
||||
.map_err(|k| InstructionError::new(instruction, k))?;
|
||||
let length: usize = to_native::<i32>(&inputs[1], instruction)?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "length").into())
|
||||
.map_err(|k| InstructionError::new(instruction, k))?;
|
||||
let memory_view = memory.view();
|
||||
|
||||
if length == 0 {
|
||||
runtime.stack.push(InterfaceValue::ByteArray(vec![]));
|
||||
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if memory_view.len() < pointer + length {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryOutOfBoundsAccess {
|
||||
index: pointer + length,
|
||||
length: memory_view.len(),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
let data: Vec<u8> = (&memory_view[pointer..pointer + length])
|
||||
.iter()
|
||||
.map(Cell::get)
|
||||
.collect();
|
||||
|
||||
log::trace!("bytearray.lift_memory: pushing {:?} on the stack", data);
|
||||
|
||||
runtime.stack.push(InterfaceValue::ByteArray(data));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
executable_instruction!(
|
||||
byte_array_lower_memory(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
let inputs = runtime.stack.pop(2).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 2 },
|
||||
)
|
||||
})?;
|
||||
|
||||
let byte_array_pointer: usize = to_native::<i32>(&inputs[0], instruction)?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "pointer").into())
|
||||
.map_err(|k| InstructionError::new(instruction, k))?;
|
||||
let byte_array: Vec<u8> = to_native(&inputs[1], instruction)?;
|
||||
let byte_array_length: i32 = byte_array.len().try_into().map_err(|_| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::NegativeValue { subject: "string_length" },
|
||||
)
|
||||
})?;
|
||||
|
||||
let instance = &mut runtime.wasm_instance;
|
||||
let memory_index: u32 = 0;
|
||||
let memory_view = instance
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?
|
||||
.view();
|
||||
|
||||
for (nth, byte) in byte_array.iter().enumerate() {
|
||||
memory_view[byte_array_pointer as usize + nth].set(*byte);
|
||||
}
|
||||
|
||||
log::trace!("bytearray.lower_memory: pushing {}, {} on the stack", byte_array_pointer, byte_array_length);
|
||||
|
||||
runtime.stack.push(InterfaceValue::I32(byte_array_pointer as i32));
|
||||
runtime.stack.push(InterfaceValue::I32(byte_array_length));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
executable_instruction!(
|
||||
byte_array_size(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
match runtime.stack.pop1() {
|
||||
Some(InterfaceValue::ByteArray(byte_array)) => {
|
||||
let length = byte_array.len() as i32;
|
||||
runtime.stack.push(InterfaceValue::I32(length));
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
Some(value) => Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::ByteArray,
|
||||
received_value: value,
|
||||
},
|
||||
)),
|
||||
|
||||
None => Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
@ -12,7 +12,7 @@ executable_instruction!(
|
||||
|
||||
let local_or_import = instance.local_or_import(index).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::LocalOrImportIsMissing {
|
||||
function_index,
|
||||
},
|
||||
@ -22,20 +22,20 @@ executable_instruction!(
|
||||
|
||||
let inputs = runtime.stack.pop(inputs_cardinality).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall {
|
||||
needed: inputs_cardinality,
|
||||
},
|
||||
)
|
||||
})?;
|
||||
|
||||
super::check_function_signature(&**instance, local_or_import, &inputs, instruction)?;
|
||||
super::check_function_signature(&**instance, local_or_import, &inputs, instruction.clone())?;
|
||||
|
||||
log::trace!("call-core: calling {} with arguments: {:?}", function_index, inputs);
|
||||
|
||||
let outputs = local_or_import.call(&inputs).map_err(|_| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::LocalOrImportCall {
|
||||
function_index,
|
||||
},
|
||||
|
@ -8,7 +8,7 @@ executable_instruction!(
|
||||
move |runtime| -> _ {
|
||||
let value = runtime.stack.peek1().ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)
|
||||
})?;
|
||||
|
@ -1,11 +1,12 @@
|
||||
mod argument_get;
|
||||
mod byte_arrays;
|
||||
mod arrays;
|
||||
mod call_core;
|
||||
mod dup;
|
||||
mod numbers;
|
||||
mod records;
|
||||
mod strings;
|
||||
mod swap2;
|
||||
mod utils;
|
||||
|
||||
use crate::interpreter::wasm;
|
||||
use crate::types::InterfaceType;
|
||||
@ -15,7 +16,7 @@ use crate::{
|
||||
values::{InterfaceValue, NativeType},
|
||||
};
|
||||
pub(crate) use argument_get::argument_get;
|
||||
pub(crate) use byte_arrays::*;
|
||||
pub(crate) use arrays::*;
|
||||
pub(crate) use call_core::call_core;
|
||||
pub(crate) use dup::dup;
|
||||
pub(crate) use numbers::*;
|
||||
@ -23,12 +24,13 @@ pub(crate) use records::*;
|
||||
use std::convert::TryFrom;
|
||||
pub(crate) use strings::*;
|
||||
pub(crate) use swap2::swap2;
|
||||
pub(self) use utils::*;
|
||||
|
||||
pub(self) const ALLOCATE_FUNC_INDEX: u32 = 0;
|
||||
pub(self) const DEALLOCATE_FUNC_INDEX: u32 = 1;
|
||||
|
||||
/// Represents all the possible WIT instructions.
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum Instruction {
|
||||
/// The `arg.get` instruction.
|
||||
ArgumentGet {
|
||||
@ -147,14 +149,17 @@ pub enum Instruction {
|
||||
/// The `string.size` instruction.
|
||||
StringSize,
|
||||
|
||||
/// The `byte_array.lift_memory` instruction.
|
||||
ByteArrayLiftMemory,
|
||||
/// The `array.lift_memory` instruction.
|
||||
ArrayLiftMemory {
|
||||
/// Array value type.
|
||||
value_type: InterfaceType,
|
||||
},
|
||||
|
||||
/// The `byte_array.lower_memory` instruction.
|
||||
ByteArrayLowerMemory,
|
||||
|
||||
/// The `string.size` instruction.
|
||||
ByteArraySize,
|
||||
/// The `array.lower_memory` instruction.
|
||||
ArrayLowerMemory {
|
||||
/// Array value type.
|
||||
value_type: InterfaceType,
|
||||
},
|
||||
|
||||
/*
|
||||
/// The `record.lift` instruction.
|
||||
@ -225,7 +230,7 @@ where
|
||||
let func_inputs = local_import.arguments();
|
||||
|
||||
for (func_input_arg, value) in func_inputs.iter().zip(values.iter()) {
|
||||
is_value_compatible_to_type(instance, &func_input_arg.ty, value, instruction)?;
|
||||
is_value_compatible_to_type(instance, &func_input_arg.ty, value, instruction.clone())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -266,7 +271,13 @@ where
|
||||
(InterfaceType::F32, InterfaceValue::F32(_)) => Ok(()),
|
||||
(InterfaceType::F64, InterfaceValue::F64(_)) => Ok(()),
|
||||
(InterfaceType::String, InterfaceValue::String(_)) => Ok(()),
|
||||
(InterfaceType::ByteArray, InterfaceValue::ByteArray(_)) => Ok(()),
|
||||
(InterfaceType::Array(ty), InterfaceValue::Array(values)) => {
|
||||
for value in values {
|
||||
is_value_compatible_to_type(instance, ty, value, instruction.clone())?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
(InterfaceType::Record(ref record_type_id), InterfaceValue::Record(record_fields)) => {
|
||||
is_record_fields_compatible_to_type(
|
||||
instance,
|
||||
@ -309,14 +320,14 @@ where
|
||||
{
|
||||
let record_type = instance.wit_record_by_id(record_type_id).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::RecordTypeByNameIsMissing { record_type_id },
|
||||
)
|
||||
})?;
|
||||
|
||||
if record_fields.len() != record_type.fields.len() {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::Record(record_type_id),
|
||||
// unwrap is safe here - len's been already checked
|
||||
@ -332,7 +343,7 @@ where
|
||||
instance,
|
||||
&record_type_field.ty,
|
||||
record_value_field,
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
)?;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ macro_rules! lowering_lifting {
|
||||
let converted_value = InterfaceValue::$to_variant(value.try_into().map_err(
|
||||
|_| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::LoweringLifting {
|
||||
from: InterfaceType::$from_variant,
|
||||
to: InterfaceType::$to_variant
|
||||
@ -35,7 +35,7 @@ macro_rules! lowering_lifting {
|
||||
}
|
||||
Some(wrong_value) => {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::$from_variant,
|
||||
received_value: wrong_value,
|
||||
@ -45,7 +45,7 @@ macro_rules! lowering_lifting {
|
||||
|
||||
None => {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
))
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
mod utils;
|
||||
|
||||
use utils::read_from_instance_mem;
|
||||
use utils::write_to_instance_mem;
|
||||
use super::read_from_instance_mem;
|
||||
use super::write_to_instance_mem;
|
||||
|
||||
use crate::interpreter::instructions::{is_record_fields_compatible_to_type, to_native};
|
||||
use crate::{
|
||||
@ -12,7 +10,6 @@ use crate::{
|
||||
vec1::Vec1,
|
||||
};
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::convert::TryInto;
|
||||
|
||||
/*
|
||||
@ -78,14 +75,14 @@ where
|
||||
let instance = &runtime.wasm_instance;
|
||||
let record_type = match instance.wit_type(type_index).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::TypeIsMissing { type_index },
|
||||
)
|
||||
})? {
|
||||
Type::Record(record_type) => record_type,
|
||||
Type::Function { .. } => {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidTypeKind {
|
||||
expected_kind: TypeKind::Record,
|
||||
received_kind: TypeKind::Function,
|
||||
@ -94,7 +91,7 @@ where
|
||||
}
|
||||
};
|
||||
let record = record_lift_(&mut runtime.stack, &record_type)
|
||||
.map_err(|k| InstructionError::new(instruction, k))?;
|
||||
.map_err(|k| InstructionError::new(instruction.clone(), k))?;
|
||||
runtime.stack.push(record);
|
||||
Ok(())
|
||||
}
|
||||
@ -102,7 +99,7 @@ where
|
||||
}
|
||||
*/
|
||||
|
||||
fn record_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
pub(super) fn record_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
record_type: &RecordType,
|
||||
offset: usize,
|
||||
@ -121,7 +118,7 @@ where
|
||||
|
||||
for field_type in record_type.fields.iter() {
|
||||
let params_count = match field_type.ty {
|
||||
InterfaceType::String | InterfaceType::ByteArray => 2,
|
||||
InterfaceType::String | InterfaceType::Array(_) => 2,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
@ -132,9 +129,9 @@ where
|
||||
}
|
||||
|
||||
let length = record_type.fields.len();
|
||||
let mut values = VecDeque::with_capacity(length);
|
||||
let mut values = Vec::with_capacity(length);
|
||||
let size = record_size(record_type);
|
||||
let data = read_from_instance_mem(instance, instruction, offset, size)?;
|
||||
let data = read_from_instance_mem(instance, instruction.clone(), offset, size)?;
|
||||
// TODO: add error handling
|
||||
let data =
|
||||
safe_transmute::transmute_many::<u64, safe_transmute::SingleManyGuard>(&data).unwrap();
|
||||
@ -144,39 +141,39 @@ where
|
||||
let value = data[field_id];
|
||||
match &field.ty {
|
||||
InterfaceType::S8 => {
|
||||
values.push_back(InterfaceValue::S8(value as _));
|
||||
values.push(InterfaceValue::S8(value as _));
|
||||
}
|
||||
InterfaceType::S16 => {
|
||||
values.push_back(InterfaceValue::S16(value as _));
|
||||
values.push(InterfaceValue::S16(value as _));
|
||||
}
|
||||
InterfaceType::S32 => {
|
||||
values.push_back(InterfaceValue::S32(value as _));
|
||||
values.push(InterfaceValue::S32(value as _));
|
||||
}
|
||||
InterfaceType::S64 => {
|
||||
values.push_back(InterfaceValue::S64(value as _));
|
||||
values.push(InterfaceValue::S64(value as _));
|
||||
}
|
||||
InterfaceType::I32 => {
|
||||
values.push_back(InterfaceValue::I32(value as _));
|
||||
values.push(InterfaceValue::I32(value as _));
|
||||
}
|
||||
InterfaceType::I64 => {
|
||||
values.push_back(InterfaceValue::I64(value as _));
|
||||
values.push(InterfaceValue::I64(value as _));
|
||||
}
|
||||
InterfaceType::U8 => {
|
||||
values.push_back(InterfaceValue::U8(value as _));
|
||||
values.push(InterfaceValue::U8(value as _));
|
||||
}
|
||||
InterfaceType::U16 => {
|
||||
values.push_back(InterfaceValue::U16(value as _));
|
||||
values.push(InterfaceValue::U16(value as _));
|
||||
}
|
||||
InterfaceType::U32 => {
|
||||
values.push_back(InterfaceValue::U32(value as _));
|
||||
values.push(InterfaceValue::U32(value as _));
|
||||
}
|
||||
InterfaceType::U64 => {
|
||||
values.push_back(InterfaceValue::U64(value as _));
|
||||
values.push(InterfaceValue::U64(value as _));
|
||||
}
|
||||
InterfaceType::F32 => {
|
||||
values.push_back(InterfaceValue::F32(value as _));
|
||||
values.push(InterfaceValue::F32(value as _));
|
||||
}
|
||||
InterfaceType::F64 => values.push_back(InterfaceValue::F64(f64::from_bits(value))),
|
||||
InterfaceType::F64 => values.push(InterfaceValue::F64(f64::from_bits(value))),
|
||||
InterfaceType::Anyref => {}
|
||||
InterfaceType::String => {
|
||||
let string_offset = value;
|
||||
@ -186,34 +183,34 @@ where
|
||||
if string_size != 0 {
|
||||
let string_mem = read_from_instance_mem(
|
||||
instance,
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
string_offset as _,
|
||||
string_size as _,
|
||||
)?;
|
||||
|
||||
// TODO: check
|
||||
let string = String::from_utf8(string_mem).unwrap();
|
||||
values.push_back(InterfaceValue::String(string));
|
||||
values.push(InterfaceValue::String(string));
|
||||
} else {
|
||||
values.push_back(InterfaceValue::String(String::new()));
|
||||
values.push(InterfaceValue::String(String::new()));
|
||||
}
|
||||
}
|
||||
InterfaceType::ByteArray => {
|
||||
InterfaceType::Array(ty) => {
|
||||
let array_offset = value;
|
||||
field_id += 1;
|
||||
let array_size = data[field_id];
|
||||
|
||||
if array_size != 0 {
|
||||
let byte_array = read_from_instance_mem(
|
||||
let array = super::array_lift_memory_(
|
||||
instance,
|
||||
instruction,
|
||||
&**ty,
|
||||
array_offset as _,
|
||||
array_size as _,
|
||||
instruction.clone(),
|
||||
)?;
|
||||
|
||||
values.push_back(InterfaceValue::ByteArray(byte_array));
|
||||
values.push(InterfaceValue::Array(array));
|
||||
} else {
|
||||
values.push_back(InterfaceValue::ByteArray(vec![]));
|
||||
values.push(InterfaceValue::Array(vec![]));
|
||||
}
|
||||
}
|
||||
InterfaceType::Record(record_type_id) => {
|
||||
@ -221,25 +218,25 @@ where
|
||||
|
||||
let record_type = instance.wit_record_by_id(*record_type_id).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::RecordTypeByNameIsMissing {
|
||||
record_type_id: *record_type_id,
|
||||
},
|
||||
)
|
||||
})?;
|
||||
|
||||
values.push_back(record_lift_memory_(
|
||||
values.push(record_lift_memory_(
|
||||
instance,
|
||||
record_type,
|
||||
offset as _,
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
)?)
|
||||
}
|
||||
}
|
||||
field_id += 1;
|
||||
}
|
||||
|
||||
utils::deallocate(instance, instruction, offset as _, size as _)?;
|
||||
super::deallocate(instance, instruction, offset as _, size as _)?;
|
||||
|
||||
Ok(InterfaceValue::Record(
|
||||
Vec1::new(values.into_iter().collect())
|
||||
@ -265,21 +262,21 @@ where
|
||||
move |runtime| -> _ {
|
||||
let inputs = runtime.stack.pop(1).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)
|
||||
})?;
|
||||
|
||||
let offset: usize = to_native::<i32>(&inputs[0], instruction)?
|
||||
let offset: usize = to_native::<i32>(&inputs[0], instruction.clone())?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "offset").into())
|
||||
.map_err(|k| InstructionError::new(instruction, k))?;
|
||||
.map_err(|k| InstructionError::new(instruction.clone(), k))?;
|
||||
|
||||
// TODO: size = 0
|
||||
let instance = &runtime.wasm_instance;
|
||||
let record_type = instance.wit_record_by_id(record_type_id).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::RecordTypeByNameIsMissing { record_type_id },
|
||||
)
|
||||
})?;
|
||||
@ -290,7 +287,8 @@ where
|
||||
record_type_id
|
||||
);
|
||||
|
||||
let record = record_lift_memory_(&**instance, record_type, offset, instruction)?;
|
||||
let record =
|
||||
record_lift_memory_(&**instance, record_type, offset, instruction.clone())?;
|
||||
|
||||
log::trace!("record.lift_memory: pushing {:?} on the stack", record);
|
||||
runtime.stack.push(record);
|
||||
@ -300,7 +298,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn record_lower_memory_<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
pub(super) fn record_lower_memory_<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &mut Instance,
|
||||
instruction: Instruction,
|
||||
values: Vec1<InterfaceValue>,
|
||||
@ -331,7 +329,7 @@ where
|
||||
InterfaceValue::F64(value) => result.push(value.to_bits()),
|
||||
InterfaceValue::String(value) => {
|
||||
let string_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction, value.as_bytes())?
|
||||
write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
@ -340,19 +338,19 @@ where
|
||||
result.push(value.len() as _);
|
||||
}
|
||||
|
||||
InterfaceValue::ByteArray(value) => {
|
||||
let byte_array_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction, &value)?
|
||||
InterfaceValue::Array(values) => {
|
||||
let (offset, size) = if !values.is_empty() {
|
||||
super::array_lower_memory_(instance, instruction.clone(), values)?
|
||||
} else {
|
||||
0
|
||||
(0, 0)
|
||||
};
|
||||
|
||||
result.push(byte_array_pointer as _);
|
||||
result.push(value.len() as _);
|
||||
result.push(offset as _);
|
||||
result.push(size as _);
|
||||
}
|
||||
|
||||
InterfaceValue::Record(values) => {
|
||||
let record_ptr = record_lower_memory_(instance, instruction, values)?;
|
||||
let record_ptr = record_lower_memory_(instance, instruction.clone(), values)?;
|
||||
|
||||
result.push(record_ptr as _);
|
||||
}
|
||||
@ -389,27 +387,28 @@ where
|
||||
&**instance,
|
||||
record_type_id,
|
||||
&record_fields,
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
)?;
|
||||
|
||||
log::trace!("record.lower_memory: obtained {:?} values on the stack for record type = {}", record_fields, record_type_id);
|
||||
|
||||
let offset = record_lower_memory_(*instance, instruction, record_fields)?;
|
||||
let offset =
|
||||
record_lower_memory_(*instance, instruction.clone(), record_fields)?;
|
||||
|
||||
log::trace!("record.lower_memory: pushing {:?} on the stack", offset);
|
||||
log::trace!("record.lower_memory: pushing {} on the stack", offset);
|
||||
runtime.stack.push(InterfaceValue::I32(offset));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Some(value) => Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::Record(record_type_id),
|
||||
received_value: value,
|
||||
},
|
||||
)),
|
||||
None => Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)),
|
||||
}
|
||||
@ -437,14 +436,14 @@ where
|
||||
let instance = &runtime.wasm_instance;
|
||||
let record_type = match instance.wit_type(type_index).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::TypeIsMissing { type_index },
|
||||
)
|
||||
})? {
|
||||
Type::Record(record_type) => record_type,
|
||||
Type::Function { .. } => {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidTypeKind {
|
||||
expected_kind: TypeKind::Record,
|
||||
received_kind: TypeKind::Function,
|
||||
@ -463,14 +462,14 @@ where
|
||||
Ok(())
|
||||
}
|
||||
Some(value) => Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::Record(record_type.clone()),
|
||||
received_type: (&value).into(),
|
||||
},
|
||||
)),
|
||||
None => Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)),
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ executable_instruction!(
|
||||
move |runtime| -> _ {
|
||||
let inputs = runtime.stack.pop(2).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 2 },
|
||||
)
|
||||
})?;
|
||||
@ -23,19 +23,19 @@ executable_instruction!(
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?;
|
||||
|
||||
let pointer: usize = to_native::<i32>(&inputs[0], instruction)?
|
||||
let pointer: usize = to_native::<i32>(&inputs[0], instruction.clone())?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "pointer").into())
|
||||
.map_err(|k| InstructionError::new(instruction, k))?;
|
||||
let length: usize = to_native::<i32>(&inputs[1], instruction)?
|
||||
.map_err(|k| InstructionError::new(instruction.clone(), k))?;
|
||||
let length: usize = to_native::<i32>(&inputs[1], instruction.clone())?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "length").into())
|
||||
.map_err(|k| InstructionError::new(instruction, k))?;
|
||||
.map_err(|k| InstructionError::new(instruction.clone(), k))?;
|
||||
let memory_view = memory.view();
|
||||
|
||||
if length == 0 {
|
||||
@ -46,7 +46,7 @@ executable_instruction!(
|
||||
|
||||
if memory_view.len() < pointer + length {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::MemoryOutOfBoundsAccess {
|
||||
index: pointer + length,
|
||||
length: memory_view.len(),
|
||||
@ -60,7 +60,7 @@ executable_instruction!(
|
||||
.collect();
|
||||
|
||||
let string = String::from_utf8(data)
|
||||
.map_err(|error| InstructionError::new(instruction, InstructionErrorKind::String(error)))?;
|
||||
.map_err(|error| InstructionError::new(instruction.clone(), InstructionErrorKind::String(error)))?;
|
||||
|
||||
log::trace!("string.lift_memory: pushing {:?} on the stack", string);
|
||||
runtime.stack.push(InterfaceValue::String(string));
|
||||
@ -75,20 +75,20 @@ executable_instruction!(
|
||||
move |runtime| -> _ {
|
||||
let inputs = runtime.stack.pop(2).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 2 },
|
||||
)
|
||||
})?;
|
||||
|
||||
let string_pointer: usize = to_native::<i32>(&inputs[0], instruction)?
|
||||
let string_pointer: usize = to_native::<i32>(&inputs[0], instruction.clone())?
|
||||
.try_into()
|
||||
.map_err(|e| (e, "pointer").into())
|
||||
.map_err(|k| InstructionError::new(instruction, k))?;
|
||||
let string: String = to_native(&inputs[1], instruction)?;
|
||||
.map_err(|k| InstructionError::new(instruction.clone(), k))?;
|
||||
let string: String = to_native(&inputs[1], instruction.clone())?;
|
||||
let string_bytes = string.as_bytes();
|
||||
let string_length: i32 = string_bytes.len().try_into().map_err(|_| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::NegativeValue { subject: "string_length" },
|
||||
)
|
||||
})?;
|
||||
@ -99,7 +99,7 @@ executable_instruction!(
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?
|
||||
@ -132,7 +132,7 @@ executable_instruction!(
|
||||
},
|
||||
|
||||
Some(value) => Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::String,
|
||||
received_value: (&value).clone(),
|
||||
@ -140,7 +140,7 @@ executable_instruction!(
|
||||
)),
|
||||
|
||||
None => Err(InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)),
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ executable_instruction!(
|
||||
move |runtime| -> _ {
|
||||
let mut values = runtime.stack.pop(2).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)
|
||||
})?;
|
||||
|
@ -29,7 +29,7 @@ where
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?
|
||||
@ -66,14 +66,14 @@ where
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
let offset = allocate(instance, instruction, bytes.len() as _)?;
|
||||
let offset = allocate(instance, instruction.clone(), bytes.len() as _)?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
let memory_view = instance
|
||||
.memory(memory_index as usize)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?
|
||||
@ -114,7 +114,7 @@ where
|
||||
let values = call_core(
|
||||
instance,
|
||||
ALLOCATE_FUNC_INDEX,
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
vec![InterfaceValue::I32(size as _)],
|
||||
)?;
|
||||
if values.len() != 1 {
|
||||
@ -169,7 +169,7 @@ where
|
||||
let index = FunctionIndex::new(function_index as usize);
|
||||
let local_or_import = instance.local_or_import(index).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::LocalOrImportIsMissing { function_index },
|
||||
)
|
||||
})?;
|
||||
@ -178,12 +178,12 @@ where
|
||||
instance,
|
||||
local_or_import,
|
||||
&inputs,
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
)?;
|
||||
|
||||
let outputs = local_or_import.call(&inputs).map_err(|_| {
|
||||
InstructionError::new(
|
||||
instruction,
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::LocalOrImportCall { function_index },
|
||||
)
|
||||
})?;
|
@ -177,7 +177,7 @@ where
|
||||
}
|
||||
|
||||
/// Transforms a `Vec<Instruction>` into an `Interpreter`.
|
||||
impl<Instance, Export, LocalImport, Memory, MemoryView> TryFrom<&Vec<Instruction>>
|
||||
impl<Instance, Export, LocalImport, Memory, MemoryView> TryFrom<Vec<Instruction>>
|
||||
for Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: wasm::structures::Export,
|
||||
@ -188,79 +188,79 @@ where
|
||||
{
|
||||
type Error = ();
|
||||
|
||||
fn try_from(instructions: &Vec<Instruction>) -> Result<Self, Self::Error> {
|
||||
fn try_from(instructions: Vec<Instruction>) -> Result<Self, Self::Error> {
|
||||
let executable_instructions = instructions
|
||||
.iter()
|
||||
.into_iter()
|
||||
.map(|instruction| match instruction {
|
||||
Instruction::ArgumentGet { index } => {
|
||||
instructions::argument_get(*index, *instruction)
|
||||
instructions::argument_get(index, instruction)
|
||||
}
|
||||
|
||||
Instruction::CallCore { function_index } => {
|
||||
instructions::call_core(*function_index, *instruction)
|
||||
instructions::call_core(function_index, instruction)
|
||||
}
|
||||
|
||||
Instruction::S8FromI32 => instructions::s8_from_i32(*instruction),
|
||||
Instruction::S8FromI64 => instructions::s8_from_i64(*instruction),
|
||||
Instruction::S16FromI32 => instructions::s16_from_i32(*instruction),
|
||||
Instruction::S16FromI64 => instructions::s16_from_i64(*instruction),
|
||||
Instruction::S32FromI32 => instructions::s32_from_i32(*instruction),
|
||||
Instruction::S32FromI64 => instructions::s32_from_i64(*instruction),
|
||||
Instruction::S64FromI32 => instructions::s64_from_i32(*instruction),
|
||||
Instruction::S64FromI64 => instructions::s64_from_i64(*instruction),
|
||||
Instruction::I32FromS8 => instructions::i32_from_s8(*instruction),
|
||||
Instruction::I32FromS16 => instructions::i32_from_s16(*instruction),
|
||||
Instruction::I32FromS32 => instructions::i32_from_s32(*instruction),
|
||||
Instruction::I32FromS64 => instructions::i32_from_s64(*instruction),
|
||||
Instruction::I64FromS8 => instructions::i64_from_s8(*instruction),
|
||||
Instruction::I64FromS16 => instructions::i64_from_s16(*instruction),
|
||||
Instruction::I64FromS32 => instructions::i64_from_s32(*instruction),
|
||||
Instruction::I64FromS64 => instructions::i64_from_s64(*instruction),
|
||||
Instruction::U8FromI32 => instructions::u8_from_i32(*instruction),
|
||||
Instruction::U8FromI64 => instructions::u8_from_i64(*instruction),
|
||||
Instruction::U16FromI32 => instructions::u16_from_i32(*instruction),
|
||||
Instruction::U16FromI64 => instructions::u16_from_i64(*instruction),
|
||||
Instruction::U32FromI32 => instructions::u32_from_i32(*instruction),
|
||||
Instruction::U32FromI64 => instructions::u32_from_i64(*instruction),
|
||||
Instruction::U64FromI32 => instructions::u64_from_i32(*instruction),
|
||||
Instruction::U64FromI64 => instructions::u64_from_i64(*instruction),
|
||||
Instruction::I32FromU8 => instructions::i32_from_u8(*instruction),
|
||||
Instruction::I32FromU16 => instructions::i32_from_u16(*instruction),
|
||||
Instruction::I32FromU32 => instructions::i32_from_u32(*instruction),
|
||||
Instruction::I32FromU64 => instructions::i32_from_u64(*instruction),
|
||||
Instruction::I64FromU8 => instructions::i64_from_u8(*instruction),
|
||||
Instruction::I64FromU16 => instructions::i64_from_u16(*instruction),
|
||||
Instruction::I64FromU32 => instructions::i64_from_u32(*instruction),
|
||||
Instruction::I64FromU64 => instructions::i64_from_u64(*instruction),
|
||||
Instruction::S8FromI32 => instructions::s8_from_i32(instruction),
|
||||
Instruction::S8FromI64 => instructions::s8_from_i64(instruction),
|
||||
Instruction::S16FromI32 => instructions::s16_from_i32(instruction),
|
||||
Instruction::S16FromI64 => instructions::s16_from_i64(instruction),
|
||||
Instruction::S32FromI32 => instructions::s32_from_i32(instruction),
|
||||
Instruction::S32FromI64 => instructions::s32_from_i64(instruction),
|
||||
Instruction::S64FromI32 => instructions::s64_from_i32(instruction),
|
||||
Instruction::S64FromI64 => instructions::s64_from_i64(instruction),
|
||||
Instruction::I32FromS8 => instructions::i32_from_s8(instruction),
|
||||
Instruction::I32FromS16 => instructions::i32_from_s16(instruction),
|
||||
Instruction::I32FromS32 => instructions::i32_from_s32(instruction),
|
||||
Instruction::I32FromS64 => instructions::i32_from_s64(instruction),
|
||||
Instruction::I64FromS8 => instructions::i64_from_s8(instruction),
|
||||
Instruction::I64FromS16 => instructions::i64_from_s16(instruction),
|
||||
Instruction::I64FromS32 => instructions::i64_from_s32(instruction),
|
||||
Instruction::I64FromS64 => instructions::i64_from_s64(instruction),
|
||||
Instruction::U8FromI32 => instructions::u8_from_i32(instruction),
|
||||
Instruction::U8FromI64 => instructions::u8_from_i64(instruction),
|
||||
Instruction::U16FromI32 => instructions::u16_from_i32(instruction),
|
||||
Instruction::U16FromI64 => instructions::u16_from_i64(instruction),
|
||||
Instruction::U32FromI32 => instructions::u32_from_i32(instruction),
|
||||
Instruction::U32FromI64 => instructions::u32_from_i64(instruction),
|
||||
Instruction::U64FromI32 => instructions::u64_from_i32(instruction),
|
||||
Instruction::U64FromI64 => instructions::u64_from_i64(instruction),
|
||||
Instruction::I32FromU8 => instructions::i32_from_u8(instruction),
|
||||
Instruction::I32FromU16 => instructions::i32_from_u16(instruction),
|
||||
Instruction::I32FromU32 => instructions::i32_from_u32(instruction),
|
||||
Instruction::I32FromU64 => instructions::i32_from_u64(instruction),
|
||||
Instruction::I64FromU8 => instructions::i64_from_u8(instruction),
|
||||
Instruction::I64FromU16 => instructions::i64_from_u16(instruction),
|
||||
Instruction::I64FromU32 => instructions::i64_from_u32(instruction),
|
||||
Instruction::I64FromU64 => instructions::i64_from_u64(instruction),
|
||||
|
||||
Instruction::StringLiftMemory => instructions::string_lift_memory(*instruction),
|
||||
Instruction::StringLowerMemory => instructions::string_lower_memory(*instruction),
|
||||
Instruction::StringSize => instructions::string_size(*instruction),
|
||||
|
||||
Instruction::ByteArrayLiftMemory => {
|
||||
instructions::byte_array_lift_memory(*instruction)
|
||||
Instruction::StringLiftMemory => instructions::string_lift_memory(instruction),
|
||||
Instruction::StringLowerMemory => instructions::string_lower_memory(instruction),
|
||||
Instruction::StringSize => instructions::string_size(instruction),
|
||||
Instruction::ArrayLiftMemory { ref value_type } => {
|
||||
let value_type = value_type.clone();
|
||||
instructions::array_lift_memory(instruction, value_type)
|
||||
}
|
||||
Instruction::ByteArrayLowerMemory => {
|
||||
instructions::byte_array_lower_memory(*instruction)
|
||||
Instruction::ArrayLowerMemory { ref value_type } => {
|
||||
let value_type = value_type.clone();
|
||||
instructions::array_lower_memory(instruction, value_type)
|
||||
}
|
||||
Instruction::ByteArraySize => instructions::byte_array_size(*instruction),
|
||||
|
||||
/*
|
||||
Instruction::RecordLift { type_index } => {
|
||||
instructions::record_lift(*type_index, *instruction)
|
||||
instructions::record_lift(*type_index, instruction)
|
||||
}
|
||||
Instruction::RecordLower { type_index } => {
|
||||
instructions::record_lower(*type_index, *instruction)
|
||||
instructions::record_lower(*type_index, instruction)
|
||||
}
|
||||
*/
|
||||
Instruction::RecordLiftMemory { record_type_id } => {
|
||||
instructions::record_lift_memory(*record_type_id as _, *instruction)
|
||||
instructions::record_lift_memory(record_type_id as _, instruction)
|
||||
}
|
||||
Instruction::RecordLowerMemory { record_type_id } => {
|
||||
instructions::record_lower_memory(*record_type_id as _, *instruction)
|
||||
instructions::record_lower_memory(record_type_id as _, instruction)
|
||||
}
|
||||
Instruction::Dup => instructions::dup(*instruction),
|
||||
Instruction::Swap2 => instructions::swap2(*instruction),
|
||||
Instruction::Dup => instructions::dup(instruction),
|
||||
Instruction::Swap2 => instructions::swap2(instruction),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -43,7 +43,7 @@ macro_rules! consume {
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// The following example creates a `foo` executable instruction,
|
||||
/// The following example creates a `foo` executable instruction.clone(),
|
||||
/// which takes 2 arguments (`x` and `y`), and does something
|
||||
/// mysterious by using the `interpreter::Runtime` API.
|
||||
///
|
||||
|
@ -129,16 +129,19 @@ impl<'de> Deserializer<'de> {
|
||||
}
|
||||
}
|
||||
|
||||
fn next_byte_array(&mut self) -> Result<&'de [u8], DeserializeError> {
|
||||
fn next_array(&mut self) -> Result<&'de [u8], DeserializeError> {
|
||||
match self.iterator.peek() {
|
||||
Some(InterfaceValue::ByteArray(v)) => {
|
||||
Some(InterfaceValue::Array(_)) => {
|
||||
self.iterator.next();
|
||||
|
||||
Ok(v)
|
||||
// Ok(v)
|
||||
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
Some(wrong_value) => Err(DeserializeError::TypeMismatch {
|
||||
expected_type: InterfaceType::ByteArray,
|
||||
// TODO: change default
|
||||
expected_type: InterfaceType::Array(Box::new(InterfaceType::S8)),
|
||||
received_value: (*wrong_value).clone(),
|
||||
}),
|
||||
|
||||
@ -217,7 +220,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
Some(InterfaceValue::F32(_)) => self.deserialize_f32(visitor),
|
||||
Some(InterfaceValue::F64(_)) => self.deserialize_f64(visitor),
|
||||
Some(InterfaceValue::String(_)) => self.deserialize_string(visitor),
|
||||
Some(InterfaceValue::ByteArray(_)) => self.deserialize_bytes(visitor),
|
||||
Some(InterfaceValue::Array(_)) => self.deserialize_bytes(visitor),
|
||||
Some(InterfaceValue::I32(_)) => self.deserialize_i32(visitor),
|
||||
Some(InterfaceValue::I64(_)) => self.deserialize_i64(visitor),
|
||||
Some(InterfaceValue::Record(..)) => unreachable!("Records should have been flattened."), // already flattened
|
||||
@ -331,7 +334,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_bytes(self.next_byte_array()?)
|
||||
visitor.visit_bytes(self.next_array()?)
|
||||
}
|
||||
|
||||
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
|
||||
|
@ -39,8 +39,8 @@ pub enum InterfaceType {
|
||||
/// A string.
|
||||
String,
|
||||
|
||||
/// A byte array.
|
||||
ByteArray,
|
||||
/// An array of values of the same type.
|
||||
Array(Box<InterfaceType>),
|
||||
|
||||
/// An `any` reference.
|
||||
Anyref,
|
||||
@ -48,7 +48,7 @@ pub enum InterfaceType {
|
||||
/// A 32-bits integer (as defined in WebAssembly core).
|
||||
I32,
|
||||
|
||||
/// A 64-bits integer (as defiend in WebAssembly core).
|
||||
/// A 64-bits integer (as defined in WebAssembly core).
|
||||
I64,
|
||||
|
||||
/// A record contains record index from interfaces AST.
|
||||
|
@ -43,7 +43,7 @@ pub enum InterfaceValue {
|
||||
String(String),
|
||||
|
||||
/// A byte array.
|
||||
ByteArray(Vec<u8>),
|
||||
Array(Vec<InterfaceValue>),
|
||||
|
||||
//Anyref(?),
|
||||
/// A 32-bits integer (as defined in WebAssembly core).
|
||||
@ -107,7 +107,6 @@ native!(u64, U64);
|
||||
native!(f32, F32);
|
||||
native!(f64, F64);
|
||||
native!(String, String);
|
||||
native!(Vec<u8>, ByteArray);
|
||||
|
||||
/// Iterates over a vector of `InterfaceValues` but flatten all the
|
||||
/// values. So `I32(1), Record([I32(2), I32(3)]), I32(4)` will be
|
||||
|
Loading…
Reference in New Issue
Block a user