mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-03 14:50:21 +00:00
update
This commit is contained in:
parent
4b5da87cca
commit
3ca9734d2e
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -22,14 +22,16 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
name = "fluence-it-types"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nom",
|
||||
"serde",
|
||||
"wast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.6"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
|
||||
[[package]]
|
||||
name = "leb128"
|
||||
@ -87,9 +89,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -128,9 +130,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.59"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
|
||||
checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@ -145,9 +147,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.48"
|
||||
version = "1.0.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
|
||||
checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4,6 +4,13 @@ version = "0.1.0"
|
||||
description = "Definitions of IValue and IType"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.118", features = ["derive", "rc"]}
|
||||
|
||||
nom = { version = "5.1", optional = true }
|
||||
wast = { version = "8.0", optional = true }
|
||||
|
||||
[features]
|
||||
impls = ["nom", "wast"]
|
||||
|
29
crates/it-types/src/impls/errors.rs
Normal file
29
crates/it-types/src/impls/errors.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt::Display;
|
||||
use std::fmt::Formatter;
|
||||
use std::fmt::Result;
|
||||
|
||||
/// Structure to represent errors when casting from an `IType`
|
||||
/// to a native value.
|
||||
#[derive(Debug)]
|
||||
pub struct WasmValueNativeCastError {
|
||||
/// The initial type.
|
||||
pub from: IValue,
|
||||
|
||||
/// The targeted type.
|
||||
///
|
||||
/// `IType` is used to represent the native type by
|
||||
/// associativity.
|
||||
pub to: IType,
|
||||
}
|
||||
|
||||
impl Error for WasmValueNativeCastError {}
|
||||
|
||||
impl Display for WasmValueNativeCastError {
|
||||
fn fmt(&self, formatter: &mut Formatter) -> Result {
|
||||
write!(formatter, "{:?}", self)
|
||||
}
|
||||
}
|
6
crates/it-types/src/impls/mod.rs
Normal file
6
crates/it-types/src/impls/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
mod errors;
|
||||
mod types;
|
||||
mod values;
|
||||
|
||||
pub use errors::WasmValueNativeCastError;
|
||||
pub use values::NativeType;
|
161
crates/it-types/src/impls/types.rs
Normal file
161
crates/it-types/src/impls/types.rs
Normal file
@ -0,0 +1,161 @@
|
||||
use crate::ne_vec::NEVec;
|
||||
use crate::IRecordFieldType;
|
||||
use crate::IRecordType;
|
||||
use crate::IType;
|
||||
|
||||
use wast::parser::Parse;
|
||||
use wast::parser::Parser;
|
||||
use wast::Error as ParseError;
|
||||
|
||||
mod keyword {
|
||||
pub use wast::{
|
||||
custom_keyword,
|
||||
kw::{anyref, export, f32, f64, func, i32, i64, import, param, result},
|
||||
};
|
||||
|
||||
// New keywords.
|
||||
custom_keyword!(record);
|
||||
custom_keyword!(field);
|
||||
|
||||
// New types.
|
||||
custom_keyword!(s8);
|
||||
custom_keyword!(s16);
|
||||
custom_keyword!(s32);
|
||||
custom_keyword!(s64);
|
||||
custom_keyword!(u8);
|
||||
custom_keyword!(u16);
|
||||
custom_keyword!(u32);
|
||||
custom_keyword!(u64);
|
||||
custom_keyword!(string);
|
||||
custom_keyword!(array);
|
||||
}
|
||||
|
||||
impl Parse<'_> for IType {
|
||||
fn parse(parser: Parser<'_>) -> Result<IType, ParseError> {
|
||||
let mut lookahead = parser.lookahead1();
|
||||
if lookahead.peek::<keyword::s8>() {
|
||||
parser.parse::<keyword::s8>()?;
|
||||
|
||||
Ok(IType::S8)
|
||||
} else if lookahead.peek::<keyword::s16>() {
|
||||
parser.parse::<keyword::s16>()?;
|
||||
|
||||
Ok(IType::S16)
|
||||
} else if lookahead.peek::<keyword::s32>() {
|
||||
parser.parse::<keyword::s32>()?;
|
||||
|
||||
Ok(IType::S32)
|
||||
} else if lookahead.peek::<keyword::s64>() {
|
||||
parser.parse::<keyword::s64>()?;
|
||||
|
||||
Ok(IType::S64)
|
||||
} else if lookahead.peek::<keyword::u8>() {
|
||||
parser.parse::<keyword::u8>()?;
|
||||
|
||||
Ok(IType::U8)
|
||||
} else if lookahead.peek::<keyword::u16>() {
|
||||
parser.parse::<keyword::u16>()?;
|
||||
|
||||
Ok(IType::U16)
|
||||
} else if lookahead.peek::<keyword::u32>() {
|
||||
parser.parse::<keyword::u32>()?;
|
||||
|
||||
Ok(IType::U32)
|
||||
} else if lookahead.peek::<keyword::u64>() {
|
||||
parser.parse::<keyword::u64>()?;
|
||||
|
||||
Ok(IType::U64)
|
||||
} else if lookahead.peek::<keyword::f32>() {
|
||||
parser.parse::<keyword::f32>()?;
|
||||
|
||||
Ok(IType::F32)
|
||||
} else if lookahead.peek::<keyword::f64>() {
|
||||
parser.parse::<keyword::f64>()?;
|
||||
|
||||
Ok(IType::F64)
|
||||
} else if lookahead.peek::<keyword::string>() {
|
||||
parser.parse::<keyword::string>()?;
|
||||
|
||||
Ok(IType::String)
|
||||
} else if lookahead.peek::<keyword::array>() {
|
||||
parser.parse::<keyword::array>()?;
|
||||
|
||||
let array_type = parser.parens(|p| p.parse())?;
|
||||
|
||||
Ok(IType::Array(Box::new(array_type)))
|
||||
} else if lookahead.peek::<keyword::anyref>() {
|
||||
parser.parse::<keyword::anyref>()?;
|
||||
|
||||
Ok(IType::Anyref)
|
||||
} else if lookahead.peek::<keyword::i32>() {
|
||||
parser.parse::<keyword::i32>()?;
|
||||
|
||||
Ok(IType::I32)
|
||||
} else if lookahead.peek::<keyword::i64>() {
|
||||
parser.parse::<keyword::i64>()?;
|
||||
|
||||
Ok(IType::I64)
|
||||
} else if lookahead.peek::<keyword::record>() {
|
||||
parser.parse::<keyword::record>()?;
|
||||
|
||||
Ok(IType::Record(parser.parse()?))
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse<'_> for IRecordType {
|
||||
fn parse(parser: Parser<'_>) -> Result<Self, ParseError> {
|
||||
parser.parse::<keyword::record>()?;
|
||||
|
||||
let record_name = parser
|
||||
.step(|cursor| {
|
||||
cursor
|
||||
.id()
|
||||
.ok_or_else(|| cursor.error("expecting argument identifier"))
|
||||
})?
|
||||
.to_string();
|
||||
|
||||
let mut fields = vec![];
|
||||
|
||||
parser.parens(|parser| {
|
||||
while !parser.is_empty() {
|
||||
parser.parse::<keyword::field>()?;
|
||||
|
||||
let name = parser
|
||||
.step(|cursor| {
|
||||
cursor
|
||||
.id()
|
||||
.ok_or_else(|| cursor.error("expecting argument identifier"))
|
||||
})?
|
||||
.to_string();
|
||||
|
||||
if !name.ends_with(':') {
|
||||
parser.step(|cursor| {
|
||||
if let Some((":", rest)) = cursor.reserved() {
|
||||
return Ok(("", rest));
|
||||
}
|
||||
Err(cursor.error("expected : between an argument and a type"))
|
||||
})?;
|
||||
}
|
||||
|
||||
let ty = parser.parse()?;
|
||||
let record_field_type = IRecordFieldType {
|
||||
name: name.trim_end_matches(':').to_string(),
|
||||
ty,
|
||||
};
|
||||
|
||||
fields.push(record_field_type);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let record_type = IRecordType {
|
||||
name: record_name,
|
||||
fields: NEVec::new(fields).expect("Record must have at least one field, zero given."),
|
||||
};
|
||||
|
||||
Ok(record_type)
|
||||
}
|
||||
}
|
51
crates/it-types/src/impls/values.rs
Normal file
51
crates/it-types/src/impls/values.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::WasmValueNativeCastError;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Represents a native type supported by WIT.
|
||||
pub trait NativeType {
|
||||
/// The associated interface type that maps to the native type.
|
||||
const INTERFACE_TYPE: IType;
|
||||
}
|
||||
|
||||
macro_rules! native {
|
||||
($native_type:ty, $variant:ident) => {
|
||||
impl NativeType for $native_type {
|
||||
const INTERFACE_TYPE: IType = IType::$variant;
|
||||
}
|
||||
|
||||
impl From<$native_type> for IValue {
|
||||
fn from(n: $native_type) -> Self {
|
||||
IValue::$variant(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&IValue> for $native_type {
|
||||
type Error = WasmValueNativeCastError;
|
||||
|
||||
fn try_from(w: &IValue) -> Result<Self, Self::Error> {
|
||||
match w {
|
||||
IValue::$variant(n) => Ok(n.clone()),
|
||||
_ => Err(WasmValueNativeCastError {
|
||||
from: w.clone(),
|
||||
to: <$native_type>::INTERFACE_TYPE,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
native!(i8, S8);
|
||||
native!(i16, S16);
|
||||
native!(i32, I32);
|
||||
native!(i64, I64);
|
||||
native!(u8, U8);
|
||||
native!(u16, U16);
|
||||
native!(u32, U32);
|
||||
native!(u64, U64);
|
||||
native!(f32, F32);
|
||||
native!(f64, F64);
|
||||
native!(String, String);
|
@ -1,11 +1,20 @@
|
||||
#[cfg(feature = "impls")]
|
||||
mod impls;
|
||||
pub mod ne_vec;
|
||||
mod types;
|
||||
mod values;
|
||||
pub mod vec1;
|
||||
|
||||
// types
|
||||
pub use types::InterfaceType as IType;
|
||||
pub use types::IType;
|
||||
pub use types::RecordFieldType as IRecordFieldType;
|
||||
pub use types::RecordType as IRecordType;
|
||||
|
||||
#[cfg(feature = "impls")]
|
||||
pub use impls::NativeType;
|
||||
|
||||
// values
|
||||
pub use values::InterfaceValue as IValue;
|
||||
pub use values::IValue;
|
||||
|
||||
// errors
|
||||
#[cfg(feature = "impls")]
|
||||
pub use impls::WasmValueNativeCastError;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! `Vec1<T>` represents a non-empty `Vec<T>`.
|
||||
//! `NEVec<T>` represents a non-empty `Vec<T>`.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
@ -7,14 +7,14 @@ use std::{
|
||||
ops,
|
||||
};
|
||||
|
||||
/// `Vec1<T>` represents a non-empty `Vec<T>`. It derefs to `Vec<T>`
|
||||
/// `NEVec<T>` represents a non-empty `Vec<T>`. It derefs to `Vec<T>`
|
||||
/// directly.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Hash, Deserialize, Default)]
|
||||
pub struct Vec1<T>(Vec<T>)
|
||||
pub struct NEVec<T>(Vec<T>)
|
||||
where
|
||||
T: Debug;
|
||||
|
||||
/// Represents the only error that can be emitted by `Vec1`, i.e. when
|
||||
/// Represents the only error that can be emitted by `NEVec`, i.e. when
|
||||
/// the number of items is zero.
|
||||
#[derive(Debug)]
|
||||
pub struct EmptyVec;
|
||||
@ -23,11 +23,14 @@ impl error::Error for EmptyVec {}
|
||||
|
||||
impl fmt::Display for EmptyVec {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(formatter, "Vec1 must as least contain one item, zero given")
|
||||
write!(
|
||||
formatter,
|
||||
"NEVec must as least contain one item, zero given"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Vec1<T>
|
||||
impl<T> NEVec<T>
|
||||
where
|
||||
T: Debug,
|
||||
{
|
||||
@ -41,13 +44,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts this Vec1 into Vec
|
||||
/// Converts this NEVec into Vec
|
||||
pub fn into_vec(self) -> Vec<T> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Vec1<T>
|
||||
impl<T> fmt::Debug for NEVec<T>
|
||||
where
|
||||
T: Debug,
|
||||
{
|
||||
@ -56,7 +59,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ops::Deref for Vec1<T>
|
||||
impl<T> ops::Deref for NEVec<T>
|
||||
where
|
||||
T: Debug,
|
||||
{
|
@ -1,13 +1,13 @@
|
||||
//! This module defines the WIT types.
|
||||
|
||||
use crate::vec1::Vec1;
|
||||
use crate::ne_vec::NEVec;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
/// Represents the types supported by WIT.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub enum InterfaceType {
|
||||
pub enum IType {
|
||||
/// A 8-bits signed integer.
|
||||
S8,
|
||||
|
||||
@ -42,7 +42,7 @@ pub enum InterfaceType {
|
||||
String,
|
||||
|
||||
/// An array of values of the same type.
|
||||
Array(Box<InterfaceType>),
|
||||
Array(Box<IType>),
|
||||
|
||||
/// An `any` reference.
|
||||
Anyref,
|
||||
@ -65,7 +65,7 @@ pub struct RecordFieldType {
|
||||
pub name: String,
|
||||
|
||||
/// A field type.
|
||||
pub ty: InterfaceType,
|
||||
pub ty: IType,
|
||||
}
|
||||
|
||||
/// Represents a record type.
|
||||
@ -77,18 +77,64 @@ pub struct RecordType {
|
||||
/// Types and names representing the fields.
|
||||
/// A record must have at least one field, hence the
|
||||
/// [`Vec1`][crate::vec1::Vec1].
|
||||
pub fields: Vec1<RecordFieldType>,
|
||||
pub fields: NEVec<RecordFieldType>,
|
||||
}
|
||||
|
||||
impl Default for RecordType {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: String::new(),
|
||||
fields: Vec1::new(vec![RecordFieldType {
|
||||
fields: NEVec::new(vec![RecordFieldType {
|
||||
name: String::new(),
|
||||
ty: InterfaceType::S8,
|
||||
ty: IType::S8,
|
||||
}])
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode an `IType` into a string.
|
||||
// TODO: consider change to impl Display
|
||||
impl ToString for &IType {
|
||||
fn to_string(&self) -> String {
|
||||
match &self {
|
||||
IType::S8 => "s8".to_string(),
|
||||
IType::S16 => "s16".to_string(),
|
||||
IType::S32 => "s32".to_string(),
|
||||
IType::S64 => "s64".to_string(),
|
||||
IType::U8 => "u8".to_string(),
|
||||
IType::U16 => "u16".to_string(),
|
||||
IType::U32 => "u32".to_string(),
|
||||
IType::U64 => "u64".to_string(),
|
||||
IType::F32 => "f32".to_string(),
|
||||
IType::F64 => "f64".to_string(),
|
||||
IType::String => "string".to_string(),
|
||||
IType::Array(ty) => format!("array ({})", ty.as_ref().to_string()),
|
||||
IType::Anyref => "anyref".to_string(),
|
||||
IType::I32 => "i32".to_string(),
|
||||
IType::I64 => "i64".to_string(),
|
||||
IType::Record(record_type_id) => format!("record {}", record_type_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for &RecordType {
|
||||
fn to_string(&self) -> String {
|
||||
format!(
|
||||
"record ${} (\n{fields})",
|
||||
self.name,
|
||||
fields = self
|
||||
.fields
|
||||
.iter()
|
||||
.fold(String::new(), |mut accumulator, field_type| {
|
||||
accumulator.push(' ');
|
||||
accumulator.push_str(&format!(
|
||||
"field ${}: {}\n",
|
||||
field_type.name,
|
||||
(&field_type.ty).to_string()
|
||||
));
|
||||
accumulator
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
//! Defines WIT values and associated operations.
|
||||
|
||||
use crate::vec1::Vec1;
|
||||
use crate::ne_vec::NEVec;
|
||||
|
||||
/// A WIT value.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum InterfaceValue {
|
||||
pub enum IValue {
|
||||
/// A 8-bits signed integer.
|
||||
S8(i8),
|
||||
|
||||
@ -39,7 +39,7 @@ pub enum InterfaceValue {
|
||||
String(String),
|
||||
|
||||
/// A byte array.
|
||||
Array(Vec<InterfaceValue>),
|
||||
Array(Vec<IValue>),
|
||||
|
||||
//Anyref(?),
|
||||
/// A 32-bits integer (as defined in WebAssembly core).
|
||||
@ -49,10 +49,10 @@ pub enum InterfaceValue {
|
||||
I64(i64),
|
||||
|
||||
/// A record.
|
||||
Record(Vec1<InterfaceValue>),
|
||||
Record(NEVec<IValue>),
|
||||
}
|
||||
|
||||
impl Default for InterfaceValue {
|
||||
impl Default for IValue {
|
||||
fn default() -> Self {
|
||||
Self::I32(0)
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ fn test_binary_encoding_decoding_roundtrip() {
|
||||
outputs: vec![],
|
||||
},
|
||||
Type::Function {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::S32],
|
||||
inputs: vec![IType::I32, IType::I32],
|
||||
outputs: vec![IType::S32],
|
||||
},
|
||||
Type::Record(RecordType {
|
||||
fields: vec1![InterfaceType::String, InterfaceType::I32],
|
||||
fields: vec1![IType::String, IType::I32],
|
||||
}),
|
||||
],
|
||||
imports: vec![Import {
|
||||
|
@ -8,7 +8,7 @@ repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
fluence-it-types = { path = "../crates/it-types", version = "0.1.0" }
|
||||
fluence-it-types = { path = "../crates/it-types", version = "0.1.0", features = ["impls"] }
|
||||
|
||||
nom = "5.1"
|
||||
wast = "8.0"
|
||||
|
@ -1,12 +1,7 @@
|
||||
//! Represents the WIT language as a tree. This is the central
|
||||
//! representation of the language.
|
||||
|
||||
use crate::{
|
||||
interpreter::Instruction,
|
||||
IValue,
|
||||
IType,
|
||||
IRecordType
|
||||
};
|
||||
use crate::{interpreter::Instruction, IRecordType, IType};
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
@ -1,9 +1,9 @@
|
||||
//! Parse the WIT binary representation into an [AST](crate::ast).
|
||||
|
||||
use crate::IRecordFieldType;
|
||||
use crate::IRecordType;
|
||||
use crate::IType;
|
||||
use crate::RecordFieldType;
|
||||
use crate::RecordType;
|
||||
use crate::{ast::*, interpreter::Instruction, types::*};
|
||||
use crate::{ast::*, interpreter::Instruction};
|
||||
use nom::{
|
||||
error::{make_error, ErrorKind, ParseError},
|
||||
Err, IResult,
|
||||
@ -76,7 +76,7 @@ fn uleb<'input, E: ParseError<&'input [u8]>>(input: &'input [u8]) -> IResult<&'i
|
||||
|
||||
fn record_field<'input, E: ParseError<&'input [u8]>>(
|
||||
mut input: &'input [u8],
|
||||
) -> IResult<&'input [u8], RecordFieldType, E> {
|
||||
) -> IResult<&'input [u8], IRecordFieldType, E> {
|
||||
if input.is_empty() {
|
||||
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
||||
}
|
||||
@ -84,7 +84,7 @@ fn record_field<'input, E: ParseError<&'input [u8]>>(
|
||||
consume!((input, name) = owned_string(input)?);
|
||||
consume!((input, ty) = ty(input)?);
|
||||
|
||||
Ok((input, RecordFieldType { name, ty }))
|
||||
Ok((input, IRecordFieldType { name, ty }))
|
||||
}
|
||||
|
||||
fn function_arg<'input, E: ParseError<&'input [u8]>>(
|
||||
@ -144,17 +144,17 @@ fn ty<'input, E: ParseError<&'input [u8]>>(
|
||||
/// Parse a record type.
|
||||
fn record_type<'input, E: ParseError<&'input [u8]>>(
|
||||
input: &'input [u8],
|
||||
) -> IResult<&'input [u8], RecordType, E> {
|
||||
use crate::vec1::Vec1;
|
||||
) -> IResult<&'input [u8], IRecordType, E> {
|
||||
use crate::NEVec;
|
||||
|
||||
let (output, name) = owned_string(input)?;
|
||||
let (output, fields) = list(output, record_field)?;
|
||||
|
||||
Ok((
|
||||
output,
|
||||
RecordType {
|
||||
IRecordType {
|
||||
name,
|
||||
fields: Vec1::new(fields).expect("Record must have at least one field, zero given."),
|
||||
fields: NEVec::new(fields).expect("Record must have at least one field, zero given."),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -1,12 +1,7 @@
|
||||
//! Parse the WIT textual representation into an [AST](crate::ast).
|
||||
|
||||
use crate::IType;
|
||||
use crate::ITypeImpl;
|
||||
use crate::RecordFieldType;
|
||||
use crate::RecordFieldTypeImpl;
|
||||
use crate::RecordType;
|
||||
use crate::RecordTypeImpl;
|
||||
use crate::{ast::*, interpreter::Instruction, types::*, vec1::Vec1};
|
||||
use crate::{ast::*, interpreter::Instruction};
|
||||
use std::rc::Rc;
|
||||
pub use wast::parser::ParseBuffer as Buffer;
|
||||
use wast::parser::{self, Cursor, Parse, Parser, Peek, Result};
|
||||
@ -89,138 +84,6 @@ mod keyword {
|
||||
custom_keyword!(swap2 = "swap2");
|
||||
}
|
||||
|
||||
impl Parse<'_> for ITypeImpl {
|
||||
fn parse(parser: Parser<'_>) -> Result<IType> {
|
||||
let mut lookahead = parser.lookahead1();
|
||||
if lookahead.peek::<keyword::s8>() {
|
||||
parser.parse::<keyword::s8>()?;
|
||||
|
||||
Ok(IType::S8)
|
||||
} else if lookahead.peek::<keyword::s16>() {
|
||||
parser.parse::<keyword::s16>()?;
|
||||
|
||||
Ok(IType::S16)
|
||||
} else if lookahead.peek::<keyword::s32>() {
|
||||
parser.parse::<keyword::s32>()?;
|
||||
|
||||
Ok(IType::S32)
|
||||
} else if lookahead.peek::<keyword::s64>() {
|
||||
parser.parse::<keyword::s64>()?;
|
||||
|
||||
Ok(IType::S64)
|
||||
} else if lookahead.peek::<keyword::u8>() {
|
||||
parser.parse::<keyword::u8>()?;
|
||||
|
||||
Ok(IType::U8)
|
||||
} else if lookahead.peek::<keyword::u16>() {
|
||||
parser.parse::<keyword::u16>()?;
|
||||
|
||||
Ok(IType::U16)
|
||||
} else if lookahead.peek::<keyword::u32>() {
|
||||
parser.parse::<keyword::u32>()?;
|
||||
|
||||
Ok(IType::U32)
|
||||
} else if lookahead.peek::<keyword::u64>() {
|
||||
parser.parse::<keyword::u64>()?;
|
||||
|
||||
Ok(IType::U64)
|
||||
} else if lookahead.peek::<keyword::f32>() {
|
||||
parser.parse::<keyword::f32>()?;
|
||||
|
||||
Ok(IType::F32)
|
||||
} else if lookahead.peek::<keyword::f64>() {
|
||||
parser.parse::<keyword::f64>()?;
|
||||
|
||||
Ok(IType::F64)
|
||||
} else if lookahead.peek::<keyword::string>() {
|
||||
parser.parse::<keyword::string>()?;
|
||||
|
||||
Ok(IType::String)
|
||||
} else if lookahead.peek::<keyword::array>() {
|
||||
parser.parse::<keyword::array>()?;
|
||||
|
||||
let array_type = parser.parens(|p| p.parse())?;
|
||||
|
||||
Ok(IType::Array(Box::new(array_type)))
|
||||
} else if lookahead.peek::<keyword::anyref>() {
|
||||
parser.parse::<keyword::anyref>()?;
|
||||
|
||||
Ok(IType::Anyref)
|
||||
} else if lookahead.peek::<keyword::i32>() {
|
||||
parser.parse::<keyword::i32>()?;
|
||||
|
||||
Ok(IType::I32)
|
||||
} else if lookahead.peek::<keyword::i64>() {
|
||||
parser.parse::<keyword::i64>()?;
|
||||
|
||||
Ok(IType::I64)
|
||||
} else if lookahead.peek::<keyword::record>() {
|
||||
parser.parse::<keyword::record>()?;
|
||||
|
||||
Ok(IType::Record(parser.parse()?))
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse<'_> for RecordTypeImpl {
|
||||
fn parse(parser: Parser<'_>) -> Result<Self> {
|
||||
parser.parse::<keyword::record>()?;
|
||||
|
||||
let record_name = parser
|
||||
.step(|cursor| {
|
||||
cursor
|
||||
.id()
|
||||
.ok_or_else(|| cursor.error("expecting argument identifier"))
|
||||
})?
|
||||
.to_string();
|
||||
|
||||
let mut fields = vec![];
|
||||
|
||||
parser.parens(|parser| {
|
||||
while !parser.is_empty() {
|
||||
parser.parse::<keyword::field>()?;
|
||||
|
||||
let name = parser
|
||||
.step(|cursor| {
|
||||
cursor
|
||||
.id()
|
||||
.ok_or_else(|| cursor.error("expecting argument identifier"))
|
||||
})?
|
||||
.to_string();
|
||||
|
||||
if !name.ends_with(':') {
|
||||
parser.step(|cursor| {
|
||||
if let Some((":", rest)) = cursor.reserved() {
|
||||
return Ok(("", rest));
|
||||
}
|
||||
Err(cursor.error("expected : between an argument and a type"))
|
||||
})?;
|
||||
}
|
||||
|
||||
let ty = parser.parse()?;
|
||||
let record_field_type = RecordFieldType {
|
||||
name: name.trim_end_matches(":").to_string(),
|
||||
ty,
|
||||
};
|
||||
let record_field_type = RecordFieldTypeImpl(record_field_type);
|
||||
|
||||
fields.push(record_field_type);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let record_type = RecordType {
|
||||
name: record_name,
|
||||
fields: Vec1::new(fields).expect("Record must have at least one field, zero given."),
|
||||
};
|
||||
let record_type = RecordTypeImpl(record_type);
|
||||
|
||||
Ok(record_type)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::suspicious_else_formatting)]
|
||||
impl<'a> Parse<'a> for Instruction {
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
|
@ -1,12 +1,14 @@
|
||||
//! Writes the AST into bytes representing WIT with its binary format.
|
||||
|
||||
use crate::{ast::*, interpreter::Instruction, types::*};
|
||||
use std::io::{self, Write};
|
||||
use crate::{ast::*, interpreter::Instruction};
|
||||
|
||||
use crate::IRecordFieldType;
|
||||
use crate::IRecordType;
|
||||
use crate::IType;
|
||||
use crate::ITypeImpl;
|
||||
use crate::RecordFieldTypeImpl;
|
||||
use crate::RecordTypeImpl;
|
||||
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// A trait for converting a value to bytes.
|
||||
pub trait ToBytes<W>
|
||||
@ -17,6 +19,15 @@ where
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()>;
|
||||
}
|
||||
|
||||
/// Miscellaneous IType wrapper to pass the orphan rule.
|
||||
pub struct ITypeImpl<'a>(pub &'a IType);
|
||||
|
||||
/// Miscellaneous IRecordType wrapper to pass the orphan rule.
|
||||
pub struct IRecordTypeImpl<'a>(pub &'a IRecordType);
|
||||
|
||||
/// Miscellaneous IRecordFieldType wrapper to pass the orphan rule.
|
||||
pub struct IRecordFieldTypeImpl<'a>(pub &'a IRecordFieldType);
|
||||
|
||||
/// Encode a `u8` into a byte (well, it's already a byte!).
|
||||
impl<W> ToBytes<W> for u8
|
||||
where
|
||||
@ -53,6 +64,72 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode an `IType` into bytes.
|
||||
impl<W> ToBytes<W> for ITypeImpl<'_>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
match &self.0 {
|
||||
IType::S8 => 0x00_u8.to_bytes(writer),
|
||||
IType::S16 => 0x01_u8.to_bytes(writer),
|
||||
IType::S32 => 0x02_u8.to_bytes(writer),
|
||||
IType::S64 => 0x03_u8.to_bytes(writer),
|
||||
IType::U8 => 0x04_u8.to_bytes(writer),
|
||||
IType::U16 => 0x05_u8.to_bytes(writer),
|
||||
IType::U32 => 0x06_u8.to_bytes(writer),
|
||||
IType::U64 => 0x07_u8.to_bytes(writer),
|
||||
IType::F32 => 0x08_u8.to_bytes(writer),
|
||||
IType::F64 => 0x09_u8.to_bytes(writer),
|
||||
IType::String => 0x0a_u8.to_bytes(writer),
|
||||
IType::Array(ty) => {
|
||||
0x36_u8.to_bytes(writer)?;
|
||||
let itype_impl = ITypeImpl(ty);
|
||||
itype_impl.to_bytes(writer)
|
||||
}
|
||||
IType::Anyref => 0x0b_u8.to_bytes(writer),
|
||||
IType::I32 => 0x0c_u8.to_bytes(writer),
|
||||
IType::I64 => 0x0d_u8.to_bytes(writer),
|
||||
IType::Record(record_id) => {
|
||||
0x0e_u8.to_bytes(writer)?;
|
||||
record_id.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a `RecordType` into bytes.
|
||||
impl<W> ToBytes<W> for IRecordFieldTypeImpl<'_>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
let record_field_type = &self.0;
|
||||
record_field_type.name.as_str().to_bytes(writer)?;
|
||||
let itype_impl = ITypeImpl(&record_field_type.ty);
|
||||
itype_impl.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a `RecordType` into bytes.
|
||||
impl<W> ToBytes<W> for IRecordTypeImpl<'_>
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
let record_type = self.0;
|
||||
record_type.name.as_str().to_bytes(writer)?;
|
||||
let record_type_impl = record_type
|
||||
.fields
|
||||
.deref()
|
||||
.iter()
|
||||
.map(|r| IRecordFieldTypeImpl(r))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
record_type_impl.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a `str` into bytes.
|
||||
///
|
||||
/// Decoder is `decoders::binary::string`.
|
||||
@ -110,63 +187,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode an `InterfaceType` into bytes.
|
||||
impl<W> ToBytes<W> for ITypeImpl
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
match self.0 {
|
||||
IType::S8 => 0x00_u8.to_bytes(writer),
|
||||
IType::S16 => 0x01_u8.to_bytes(writer),
|
||||
IType::S32 => 0x02_u8.to_bytes(writer),
|
||||
IType::S64 => 0x03_u8.to_bytes(writer),
|
||||
IType::U8 => 0x04_u8.to_bytes(writer),
|
||||
IType::U16 => 0x05_u8.to_bytes(writer),
|
||||
IType::U32 => 0x06_u8.to_bytes(writer),
|
||||
IType::U64 => 0x07_u8.to_bytes(writer),
|
||||
IType::F32 => 0x08_u8.to_bytes(writer),
|
||||
IType::F64 => 0x09_u8.to_bytes(writer),
|
||||
IType::String => 0x0a_u8.to_bytes(writer),
|
||||
IType::Array(ty) => {
|
||||
0x36_u8.to_bytes(writer)?;
|
||||
ty.to_bytes(writer)
|
||||
}
|
||||
IType::Anyref => 0x0b_u8.to_bytes(writer),
|
||||
IType::I32 => 0x0c_u8.to_bytes(writer),
|
||||
IType::I64 => 0x0d_u8.to_bytes(writer),
|
||||
IType::Record(record_id) => {
|
||||
0x0e_u8.to_bytes(writer)?;
|
||||
record_id.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a `RecordType` into bytes.
|
||||
impl<W> ToBytes<W> for RecordFieldTypeImpl
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
let record_field_type = &self.0;
|
||||
record_field_type.name.as_str().to_bytes(writer)?;
|
||||
record_field_type.ty.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a `RecordType` into bytes.
|
||||
impl<W> ToBytes<W> for RecordTypeImpl
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
let record_type = &self.0;
|
||||
record_type.name.as_str().to_bytes(writer)?;
|
||||
record_type.fields.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a `TypeKind` into bytes.
|
||||
impl<W> ToBytes<W> for TypeKind
|
||||
where
|
||||
@ -202,7 +222,8 @@ where
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
self.name.to_bytes(writer)?;
|
||||
self.ty.to_bytes(writer)
|
||||
let itype_impl = ITypeImpl(&self.ty);
|
||||
itype_impl.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,12 +242,17 @@ where
|
||||
} => {
|
||||
TypeKind::Function.to_bytes(writer)?;
|
||||
arguments.to_bytes(writer)?;
|
||||
let output_types = output_types
|
||||
.iter()
|
||||
.map(|t| ITypeImpl(t))
|
||||
.collect::<Vec<_>>();
|
||||
output_types.to_bytes(writer)?;
|
||||
}
|
||||
|
||||
Type::Record(record_type) => {
|
||||
TypeKind::Record.to_bytes(writer)?;
|
||||
record_type.to_bytes(writer)?;
|
||||
let record_impl = IRecordTypeImpl(record_type.deref());
|
||||
record_impl.to_bytes(writer)?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -390,11 +416,13 @@ where
|
||||
|
||||
Instruction::ArrayLiftMemory { value_type } => {
|
||||
0x37_u8.to_bytes(writer)?;
|
||||
value_type.to_bytes(writer)?
|
||||
let value_type_impl = ITypeImpl(value_type);
|
||||
value_type_impl.to_bytes(writer)?
|
||||
}
|
||||
Instruction::ArrayLowerMemory { value_type } => {
|
||||
0x38_u8.to_bytes(writer)?;
|
||||
value_type.to_bytes(writer)?
|
||||
let value_type_impl = ITypeImpl(value_type);
|
||||
value_type_impl.to_bytes(writer)?
|
||||
}
|
||||
/*
|
||||
Instruction::ArraySize => 0x39_u8.to_bytes(writer)?,
|
||||
@ -505,23 +533,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_interface_type() {
|
||||
assert_to_bytes!(InterfaceType::S8, &[0x00]);
|
||||
assert_to_bytes!(InterfaceType::S16, &[0x01]);
|
||||
assert_to_bytes!(InterfaceType::S32, &[0x02]);
|
||||
assert_to_bytes!(InterfaceType::S64, &[0x03]);
|
||||
assert_to_bytes!(InterfaceType::U8, &[0x04]);
|
||||
assert_to_bytes!(InterfaceType::U16, &[0x05]);
|
||||
assert_to_bytes!(InterfaceType::U32, &[0x06]);
|
||||
assert_to_bytes!(InterfaceType::U64, &[0x07]);
|
||||
assert_to_bytes!(InterfaceType::F32, &[0x08]);
|
||||
assert_to_bytes!(InterfaceType::F64, &[0x09]);
|
||||
assert_to_bytes!(InterfaceType::String, &[0x0a]);
|
||||
assert_to_bytes!(InterfaceType::Anyref, &[0x0b]);
|
||||
assert_to_bytes!(InterfaceType::I32, &[0x0c]);
|
||||
assert_to_bytes!(InterfaceType::I64, &[0x0d]);
|
||||
assert_to_bytes!(IType::S8, &[0x00]);
|
||||
assert_to_bytes!(IType::S16, &[0x01]);
|
||||
assert_to_bytes!(IType::S32, &[0x02]);
|
||||
assert_to_bytes!(IType::S64, &[0x03]);
|
||||
assert_to_bytes!(IType::U8, &[0x04]);
|
||||
assert_to_bytes!(IType::U16, &[0x05]);
|
||||
assert_to_bytes!(IType::U32, &[0x06]);
|
||||
assert_to_bytes!(IType::U64, &[0x07]);
|
||||
assert_to_bytes!(IType::F32, &[0x08]);
|
||||
assert_to_bytes!(IType::F64, &[0x09]);
|
||||
assert_to_bytes!(IType::String, &[0x0a]);
|
||||
assert_to_bytes!(IType::Anyref, &[0x0b]);
|
||||
assert_to_bytes!(IType::I32, &[0x0c]);
|
||||
assert_to_bytes!(IType::I64, &[0x0d]);
|
||||
assert_to_bytes!(
|
||||
InterfaceType::Record(RecordType {
|
||||
fields: vec1![InterfaceType::String]
|
||||
IType::Record(RecordType {
|
||||
fields: vec1![IType::String]
|
||||
}),
|
||||
&[0x0e, 0x01, 0x0a]
|
||||
);
|
||||
@ -531,7 +559,7 @@ mod tests {
|
||||
fn test_record_type() {
|
||||
assert_to_bytes!(
|
||||
RecordType {
|
||||
fields: vec1![InterfaceType::String]
|
||||
fields: vec1![IType::String]
|
||||
},
|
||||
&[
|
||||
0x01, // 1 field
|
||||
@ -540,7 +568,7 @@ mod tests {
|
||||
);
|
||||
assert_to_bytes!(
|
||||
RecordType {
|
||||
fields: vec1![InterfaceType::String, InterfaceType::I32]
|
||||
fields: vec1![IType::String, IType::I32]
|
||||
},
|
||||
&[
|
||||
0x02, // 2 fields
|
||||
@ -551,11 +579,11 @@ mod tests {
|
||||
assert_to_bytes!(
|
||||
RecordType {
|
||||
fields: vec1![
|
||||
InterfaceType::String,
|
||||
InterfaceType::Record(RecordType {
|
||||
fields: vec1![InterfaceType::I32, InterfaceType::I32],
|
||||
IType::String,
|
||||
IType::Record(RecordType {
|
||||
fields: vec1![IType::I32, IType::I32],
|
||||
}),
|
||||
InterfaceType::F64,
|
||||
IType::F64,
|
||||
],
|
||||
},
|
||||
&[
|
||||
@ -600,8 +628,8 @@ mod tests {
|
||||
fn test_type_function() {
|
||||
assert_to_bytes!(
|
||||
Type::Function {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I64],
|
||||
outputs: vec![InterfaceType::S32],
|
||||
inputs: vec![IType::I32, IType::I64],
|
||||
outputs: vec![IType::S32],
|
||||
},
|
||||
&[
|
||||
0x00, // function type
|
||||
@ -618,7 +646,7 @@ mod tests {
|
||||
fn test_type_record() {
|
||||
assert_to_bytes!(
|
||||
Type::Record(RecordType {
|
||||
fields: vec1![InterfaceType::I32, InterfaceType::I64],
|
||||
fields: vec1![IType::I32, IType::I64],
|
||||
}),
|
||||
&[
|
||||
0x01, // record type
|
||||
@ -667,8 +695,8 @@ mod tests {
|
||||
assert_to_bytes!(
|
||||
Interfaces {
|
||||
types: vec![Type::Function {
|
||||
inputs: vec![InterfaceType::S8],
|
||||
outputs: vec![InterfaceType::S16],
|
||||
inputs: vec![IType::S8],
|
||||
outputs: vec![IType::S16],
|
||||
}],
|
||||
imports: vec![Import {
|
||||
namespace: "ab",
|
||||
|
@ -7,13 +7,13 @@
|
||||
//! ast::{Adapter, Export, Implementation, Import, Interfaces, Type},
|
||||
//! encoders::wat::*,
|
||||
//! interpreter::Instruction,
|
||||
//! types::InterfaceType,
|
||||
//! types::IType,
|
||||
//! };
|
||||
//!
|
||||
//! let input: String = (&Interfaces {
|
||||
//! types: vec![Type::Function {
|
||||
//! inputs: vec![InterfaceType::I32],
|
||||
//! outputs: vec![InterfaceType::S8],
|
||||
//! inputs: vec![IType::I32],
|
||||
//! outputs: vec![IType::S8],
|
||||
//! }],
|
||||
//! imports: vec![Import {
|
||||
//! namespace: "ns",
|
||||
@ -56,58 +56,9 @@
|
||||
//! ```
|
||||
|
||||
use crate::IType;
|
||||
use crate::ITypeImpl;
|
||||
use crate::RecordTypeImpl;
|
||||
use crate::{ast::*, interpreter::Instruction, types::*};
|
||||
use crate::{ast::*, interpreter::Instruction};
|
||||
use std::string::ToString;
|
||||
|
||||
/// Encode an `InterfaceType` into a string.
|
||||
impl ToString for &ITypeImpl {
|
||||
fn to_string(&self) -> String {
|
||||
match &self.0 {
|
||||
IType::S8 => "s8".to_string(),
|
||||
IType::S16 => "s16".to_string(),
|
||||
IType::S32 => "s32".to_string(),
|
||||
IType::S64 => "s64".to_string(),
|
||||
IType::U8 => "u8".to_string(),
|
||||
IType::U16 => "u16".to_string(),
|
||||
IType::U32 => "u32".to_string(),
|
||||
IType::U64 => "u64".to_string(),
|
||||
IType::F32 => "f32".to_string(),
|
||||
IType::F64 => "f64".to_string(),
|
||||
IType::String => "string".to_string(),
|
||||
IType::Array(ty) => format!("array ({})", ty.as_ref().to_string()),
|
||||
IType::Anyref => "anyref".to_string(),
|
||||
IType::I32 => "i32".to_string(),
|
||||
IType::I64 => "i64".to_string(),
|
||||
IType::Record(record_type_id) => format!("record {}", record_type_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for &RecordTypeImpl {
|
||||
fn to_string(&self) -> String {
|
||||
let record_type = &self.0;
|
||||
format!(
|
||||
"record ${} (\n{fields})",
|
||||
record_type.name,
|
||||
fields =
|
||||
record_type
|
||||
.fields
|
||||
.iter()
|
||||
.fold(String::new(), |mut accumulator, field_type| {
|
||||
accumulator.push(' ');
|
||||
accumulator.push_str(&format!(
|
||||
"field ${}: {}\n",
|
||||
field_type.name,
|
||||
(&field_type.ty).to_string()
|
||||
));
|
||||
accumulator
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode an `Instruction` into a string.
|
||||
impl ToString for &Instruction {
|
||||
fn to_string(&self) -> String {
|
||||
@ -172,7 +123,7 @@ impl ToString for &Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a list of `InterfaceType` representing inputs into a
|
||||
/// Encode a list of `IType` representing inputs into a
|
||||
/// string.
|
||||
fn encode_function_arguments(arguments: &[FunctionArg]) -> String {
|
||||
// here we know that arg_names and arg_types have the same length
|
||||
@ -195,7 +146,7 @@ fn encode_function_arguments(arguments: &[FunctionArg]) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a list of `InterfaceType` representing outputs into a
|
||||
/// Encode a list of `IType` representing outputs into a
|
||||
/// string.
|
||||
fn output_types_to_result(output_types: &[IType]) -> String {
|
||||
if output_types.is_empty() {
|
||||
@ -389,22 +340,22 @@ mod tests {
|
||||
#[test]
|
||||
fn test_interface_types() {
|
||||
let inputs: Vec<String> = vec![
|
||||
(&InterfaceType::S8).to_string(),
|
||||
(&InterfaceType::S16).to_string(),
|
||||
(&InterfaceType::S32).to_string(),
|
||||
(&InterfaceType::S64).to_string(),
|
||||
(&InterfaceType::U8).to_string(),
|
||||
(&InterfaceType::U16).to_string(),
|
||||
(&InterfaceType::U32).to_string(),
|
||||
(&InterfaceType::U64).to_string(),
|
||||
(&InterfaceType::F32).to_string(),
|
||||
(&InterfaceType::F64).to_string(),
|
||||
(&InterfaceType::String).to_string(),
|
||||
(&InterfaceType::Anyref).to_string(),
|
||||
(&InterfaceType::I32).to_string(),
|
||||
(&InterfaceType::I64).to_string(),
|
||||
(&InterfaceType::Record(RecordType {
|
||||
fields: vec1![InterfaceType::String],
|
||||
(&IType::S8).to_string(),
|
||||
(&IType::S16).to_string(),
|
||||
(&IType::S32).to_string(),
|
||||
(&IType::S64).to_string(),
|
||||
(&IType::U8).to_string(),
|
||||
(&IType::U16).to_string(),
|
||||
(&IType::U32).to_string(),
|
||||
(&IType::U64).to_string(),
|
||||
(&IType::F32).to_string(),
|
||||
(&IType::F64).to_string(),
|
||||
(&IType::String).to_string(),
|
||||
(&IType::Anyref).to_string(),
|
||||
(&IType::I32).to_string(),
|
||||
(&IType::I64).to_string(),
|
||||
(&IType::Record(RecordType {
|
||||
fields: vec1![IType::String],
|
||||
}))
|
||||
.to_string(),
|
||||
];
|
||||
@ -433,20 +384,20 @@ mod tests {
|
||||
fn test_record_type() {
|
||||
let inputs = vec![
|
||||
(&RecordType {
|
||||
fields: vec1![InterfaceType::String],
|
||||
fields: vec1![IType::String],
|
||||
})
|
||||
.to_string(),
|
||||
(&RecordType {
|
||||
fields: vec1![InterfaceType::String, InterfaceType::I32],
|
||||
fields: vec1![IType::String, IType::I32],
|
||||
})
|
||||
.to_string(),
|
||||
(&RecordType {
|
||||
fields: vec1![
|
||||
InterfaceType::String,
|
||||
InterfaceType::Record(RecordType {
|
||||
fields: vec1![InterfaceType::I32, InterfaceType::I32],
|
||||
IType::String,
|
||||
IType::Record(RecordType {
|
||||
fields: vec1![IType::I32, IType::I32],
|
||||
}),
|
||||
InterfaceType::F64,
|
||||
IType::F64,
|
||||
],
|
||||
})
|
||||
.to_string(),
|
||||
@ -554,18 +505,18 @@ mod tests {
|
||||
fn test_types() {
|
||||
let inputs: Vec<String> = vec![
|
||||
(&Type::Function {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::F32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
inputs: vec![IType::I32, IType::F32],
|
||||
outputs: vec![IType::I32],
|
||||
})
|
||||
.to_string(),
|
||||
(&Type::Function {
|
||||
inputs: vec![InterfaceType::I32],
|
||||
inputs: vec![IType::I32],
|
||||
outputs: vec![],
|
||||
})
|
||||
.to_string(),
|
||||
(&Type::Function {
|
||||
inputs: vec![],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
outputs: vec![IType::I32],
|
||||
})
|
||||
.to_string(),
|
||||
(&Type::Function {
|
||||
@ -574,7 +525,7 @@ mod tests {
|
||||
})
|
||||
.to_string(),
|
||||
(&Type::Record(RecordType {
|
||||
fields: vec1![InterfaceType::String, InterfaceType::I32],
|
||||
fields: vec1![IType::String, IType::I32],
|
||||
}))
|
||||
.to_string(),
|
||||
];
|
||||
@ -635,8 +586,8 @@ mod tests {
|
||||
fn test_interfaces() {
|
||||
let input: String = (&Interfaces {
|
||||
types: vec![Type::Function {
|
||||
inputs: vec![InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::S8],
|
||||
inputs: vec![IType::I32],
|
||||
outputs: vec![IType::S8],
|
||||
}],
|
||||
imports: vec![Import {
|
||||
namespace: "ns",
|
||||
|
@ -1,8 +1,9 @@
|
||||
//! The error module contains all the data structures that represent
|
||||
//! an error.
|
||||
|
||||
use crate::values::InterfaceValue;
|
||||
use crate::{ast::TypeKind, interpreter::Instruction, types::InterfaceType};
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::{ast::TypeKind, interpreter::Instruction};
|
||||
use std::{
|
||||
error::Error,
|
||||
fmt::{self, Display, Formatter},
|
||||
@ -11,34 +12,14 @@ use std::{
|
||||
string::{self, ToString},
|
||||
};
|
||||
|
||||
pub use fluence_it_types::WasmValueNativeCastError;
|
||||
|
||||
/// A type alias for instruction's results.
|
||||
pub type InstructionResult<T> = Result<T, InstructionError>;
|
||||
|
||||
/// A type alias for the interpreter result.
|
||||
pub type InterpreterResult<T> = Result<T, InstructionError>;
|
||||
|
||||
/// Structure to represent errors when casting from an `InterfaceType`
|
||||
/// to a native value.
|
||||
#[derive(Debug)]
|
||||
pub struct WasmValueNativeCastError {
|
||||
/// The initial type.
|
||||
pub from: InterfaceValue,
|
||||
|
||||
/// The targeted type.
|
||||
///
|
||||
/// `InterfaceType` is used to represent the native type by
|
||||
/// associativity.
|
||||
pub to: InterfaceType,
|
||||
}
|
||||
|
||||
impl Error for WasmValueNativeCastError {}
|
||||
|
||||
impl Display for WasmValueNativeCastError {
|
||||
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
write!(formatter, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Structure to represent the errors for instructions.
|
||||
#[derive(Debug)]
|
||||
pub struct InstructionError {
|
||||
@ -86,20 +67,20 @@ pub enum InstructionErrorKind {
|
||||
/// Failed to cast from `from` to `to`.
|
||||
LoweringLifting {
|
||||
/// The initial type.
|
||||
from: InterfaceType,
|
||||
from: IType,
|
||||
|
||||
/// The targeted type.
|
||||
to: InterfaceType,
|
||||
to: IType,
|
||||
},
|
||||
|
||||
/// Read a value from the stack, but it doesn't have the expected
|
||||
/// type.
|
||||
InvalidValueOnTheStack {
|
||||
/// The expected type.
|
||||
expected_type: InterfaceType,
|
||||
expected_type: IType,
|
||||
|
||||
/// The received type.
|
||||
received_value: InterfaceValue,
|
||||
received_value: IValue,
|
||||
},
|
||||
|
||||
/// Need to read some values from the stack, but it doesn't
|
||||
@ -122,10 +103,10 @@ pub enum InstructionErrorKind {
|
||||
function_index: u32,
|
||||
|
||||
/// The expected signature.
|
||||
expected: (Vec<InterfaceType>, Vec<InterfaceType>),
|
||||
expected: (Vec<IType>, Vec<IType>),
|
||||
|
||||
/// The received signature.
|
||||
received: (Vec<InterfaceType>, Vec<InterfaceType>),
|
||||
received: (Vec<IType>, Vec<IType>),
|
||||
},
|
||||
|
||||
/// Failed to call a local or import function.
|
||||
|
@ -29,9 +29,9 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_argument_get =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
@ -41,20 +41,20 @@ mod tests {
|
||||
Instruction::ArgumentGet { index: 1 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(7),
|
||||
InterfaceValue::I32(42),
|
||||
IValue::I32(7),
|
||||
IValue::I32(42),
|
||||
],
|
||||
instance: Instance::new(),
|
||||
stack: [
|
||||
InterfaceValue::I32(7),
|
||||
InterfaceValue::I32(42),
|
||||
IValue::I32(7),
|
||||
IValue::I32(42),
|
||||
],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_argument_get__invalid_index =
|
||||
instructions: [Instruction::ArgumentGet { index: 1 }],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
error: "`arg.get 1` cannot access invocation inputs #1 because it doesn't exist"
|
||||
);
|
||||
|
@ -6,19 +6,18 @@ use crate::interpreter::instructions::to_native;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::Instruction,
|
||||
types::InterfaceType,
|
||||
values::InterfaceValue,
|
||||
IType, IValue,
|
||||
};
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub(super) fn array_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
value_type: &InterfaceType,
|
||||
value_type: &IType,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
instruction: Instruction,
|
||||
) -> Result<Vec<InterfaceValue>, InstructionError>
|
||||
) -> Result<Vec<IValue>, InstructionError>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
LocalImport: crate::interpreter::wasm::structures::LocalImport,
|
||||
@ -38,74 +37,58 @@ where
|
||||
let data = read_from_instance_mem(instance, instruction.clone(), offset, size)?;
|
||||
|
||||
let result_array = match value_type {
|
||||
InterfaceType::S8 => {
|
||||
IType::S8 => {
|
||||
let data = transmute_vec::<u8, i8>(data).unwrap();
|
||||
data.into_iter().map(InterfaceValue::S8).collect::<Vec<_>>()
|
||||
data.into_iter().map(IValue::S8).collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::S16 => {
|
||||
IType::S16 => {
|
||||
let data = transmute_many::<i16, AllOrNothingGuard>(&data).unwrap();
|
||||
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::S16(*v))
|
||||
.collect::<Vec<_>>()
|
||||
data.iter().map(|v| IValue::S16(*v)).collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::S32 => {
|
||||
IType::S32 => {
|
||||
let data = transmute_many::<i32, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::S32(*v))
|
||||
.collect::<Vec<_>>()
|
||||
data.iter().map(|v| IValue::S32(*v)).collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::S64 => {
|
||||
IType::S64 => {
|
||||
let data = transmute_many::<i64, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::S64(*v))
|
||||
.collect::<Vec<_>>()
|
||||
data.iter().map(|v| IValue::S64(*v)).collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::I32 => {
|
||||
IType::I32 => {
|
||||
let data = transmute_many::<i32, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::I32(*v))
|
||||
.collect::<Vec<_>>()
|
||||
data.iter().map(|v| IValue::I32(*v)).collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::I64 => {
|
||||
IType::I64 => {
|
||||
let data = transmute_many::<i64, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::S64(*v))
|
||||
.collect::<Vec<_>>()
|
||||
data.iter().map(|v| IValue::S64(*v)).collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::U8 => data.into_iter().map(InterfaceValue::U8).collect::<Vec<_>>(),
|
||||
InterfaceType::U16 => {
|
||||
IType::U8 => data.into_iter().map(IValue::U8).collect::<Vec<_>>(),
|
||||
IType::U16 => {
|
||||
let data = transmute_many::<u16, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::U16(*v))
|
||||
.collect::<Vec<_>>()
|
||||
data.iter().map(|v| IValue::U16(*v)).collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::U32 => {
|
||||
IType::U32 => {
|
||||
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter().map(|v| IValue::U32(*v)).collect::<Vec<_>>()
|
||||
}
|
||||
IType::U64 => {
|
||||
let data = transmute_many::<u64, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter().map(|v| IValue::U64(*v)).collect::<Vec<_>>()
|
||||
}
|
||||
IType::F32 => {
|
||||
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::U32(*v))
|
||||
.map(|v| IValue::F32(f32::from_bits(*v)))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
InterfaceType::U64 => {
|
||||
IType::F64 => {
|
||||
let data = transmute_many::<u64, AllOrNothingGuard>(&data).unwrap();
|
||||
data.iter()
|
||||
.map(|v| InterfaceValue::U64(*v))
|
||||
.map(|v| IValue::F64(f64::from_bits(*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 => {
|
||||
IType::Anyref => unimplemented!(),
|
||||
IType::String => {
|
||||
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
|
||||
|
||||
if data.is_empty() {
|
||||
@ -134,12 +117,12 @@ where
|
||||
|
||||
// TODO: check
|
||||
let string = String::from_utf8(string_mem).unwrap();
|
||||
result.push(InterfaceValue::String(string));
|
||||
result.push(IValue::String(string));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
InterfaceType::Array(ty) => {
|
||||
IType::Array(ty) => {
|
||||
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
|
||||
|
||||
if data.is_empty() {
|
||||
@ -167,12 +150,12 @@ where
|
||||
instruction.clone(),
|
||||
)?;
|
||||
|
||||
result.push(InterfaceValue::Array(value));
|
||||
result.push(IValue::Array(value));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
InterfaceType::Record(record_type_id) => {
|
||||
IType::Record(record_type_id) => {
|
||||
let record_type = instance.wit_record_by_id(*record_type_id).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
@ -205,7 +188,7 @@ where
|
||||
|
||||
pub(crate) fn array_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instruction: Instruction,
|
||||
value_type: InterfaceType,
|
||||
value_type: IType,
|
||||
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
@ -253,7 +236,7 @@ where
|
||||
)?;
|
||||
|
||||
log::trace!("array.lift_memory: pushing {:?} on the stack", array);
|
||||
runtime.stack.push(InterfaceValue::Array(array));
|
||||
runtime.stack.push(IValue::Array(array));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -263,7 +246,7 @@ where
|
||||
pub(super) fn array_lower_memory_<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &mut Instance,
|
||||
instruction: Instruction,
|
||||
array_values: Vec<InterfaceValue>,
|
||||
array_values: Vec<IValue>,
|
||||
) -> Result<(usize, usize), InstructionError>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
@ -278,19 +261,19 @@ where
|
||||
// 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) => {
|
||||
IValue::S8(value) => result.push(value as _),
|
||||
IValue::S16(value) => result.push(value as _),
|
||||
IValue::S32(value) => result.push(value as _),
|
||||
IValue::S64(value) => result.push(value as _),
|
||||
IValue::U8(value) => result.push(value as _),
|
||||
IValue::U16(value) => result.push(value as _),
|
||||
IValue::U32(value) => result.push(value as _),
|
||||
IValue::U64(value) => result.push(value as _),
|
||||
IValue::I32(value) => result.push(value as _),
|
||||
IValue::I64(value) => result.push(value as _),
|
||||
IValue::F32(value) => result.push(value as _),
|
||||
IValue::F64(value) => result.push(value.to_bits()),
|
||||
IValue::String(value) => {
|
||||
let string_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?
|
||||
} else {
|
||||
@ -301,7 +284,7 @@ where
|
||||
result.push(value.len() as _);
|
||||
}
|
||||
|
||||
InterfaceValue::Array(values) => {
|
||||
IValue::Array(values) => {
|
||||
let (array_offset, array_size) = if !values.is_empty() {
|
||||
array_lower_memory_(instance, instruction.clone(), values)?
|
||||
} else {
|
||||
@ -312,7 +295,7 @@ where
|
||||
result.push(array_size as _);
|
||||
}
|
||||
|
||||
InterfaceValue::Record(values) => {
|
||||
IValue::Record(values) => {
|
||||
let record_offset =
|
||||
super::record_lower_memory_(instance, instruction.clone(), values)?;
|
||||
result.push(record_offset as _);
|
||||
@ -328,7 +311,7 @@ where
|
||||
|
||||
pub(crate) fn array_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instruction: Instruction,
|
||||
value_type: InterfaceType,
|
||||
value_type: IType,
|
||||
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
@ -351,7 +334,7 @@ where
|
||||
})?;
|
||||
|
||||
match stack_value {
|
||||
InterfaceValue::Array(values) => {
|
||||
IValue::Array(values) => {
|
||||
log::trace!("array.lower_memory: obtained {:?} values on the stack for interface type {:?}", values, value_type);
|
||||
|
||||
for value in values.iter() {
|
||||
@ -371,15 +354,15 @@ where
|
||||
offset,
|
||||
size
|
||||
);
|
||||
runtime.stack.push(InterfaceValue::I32(offset as _));
|
||||
runtime.stack.push(InterfaceValue::I32(size as _));
|
||||
runtime.stack.push(IValue::I32(offset as _));
|
||||
runtime.stack.push(IValue::I32(size as _));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::Array(Box::new(value_type.clone())),
|
||||
expected_type: IType::Array(Box::new(value_type.clone())),
|
||||
received_value: stack_value.clone(),
|
||||
},
|
||||
)),
|
||||
|
@ -63,11 +63,11 @@ mod tests {
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(3),
|
||||
InterfaceValue::I32(4),
|
||||
IValue::I32(3),
|
||||
IValue::I32(4),
|
||||
],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(12)],
|
||||
stack: [IValue::I32(12)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
@ -76,8 +76,8 @@ mod tests {
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(3),
|
||||
InterfaceValue::I32(4),
|
||||
IValue::I32(3),
|
||||
IValue::I32(4),
|
||||
],
|
||||
instance: Default::default(),
|
||||
error: r#"`call-core 42` the local or import function `42` doesn't exist"#,
|
||||
@ -91,8 +91,8 @@ mod tests {
|
||||
// ^^ `42` expects 2 values on the stack, only one is present
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(3),
|
||||
InterfaceValue::I32(4),
|
||||
IValue::I32(3),
|
||||
IValue::I32(4),
|
||||
],
|
||||
instance: Instance::new(),
|
||||
error: r#"`call-core 42` needed to read `2` value(s) from the stack, but it doesn't contain enough data"#,
|
||||
@ -106,8 +106,8 @@ mod tests {
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(3),
|
||||
InterfaceValue::I64(4),
|
||||
IValue::I32(3),
|
||||
IValue::I64(4),
|
||||
// ^^^ mismatch with `42` signature
|
||||
],
|
||||
instance: Instance::new(),
|
||||
@ -122,8 +122,8 @@ mod tests {
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(3),
|
||||
InterfaceValue::I32(4),
|
||||
IValue::I32(3),
|
||||
IValue::I32(4),
|
||||
],
|
||||
instance: Instance {
|
||||
locals_or_imports: {
|
||||
@ -131,8 +131,8 @@ mod tests {
|
||||
hashmap.insert(
|
||||
42,
|
||||
LocalImport {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
inputs: vec![IType::I32, IType::I32],
|
||||
outputs: vec![IType::I32],
|
||||
function: |_| Err(()),
|
||||
// ^^^^^^^ function fails
|
||||
},
|
||||
@ -153,8 +153,8 @@ mod tests {
|
||||
Instruction::CallCore { function_index: 42 },
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(3),
|
||||
InterfaceValue::I32(4),
|
||||
IValue::I32(3),
|
||||
IValue::I32(4),
|
||||
],
|
||||
instance: Instance {
|
||||
locals_or_imports: {
|
||||
@ -162,8 +162,8 @@ mod tests {
|
||||
hashmap.insert(
|
||||
42,
|
||||
LocalImport {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
inputs: vec![IType::I32, IType::I32],
|
||||
outputs: vec![IType::I32],
|
||||
function: |_| Ok(vec![]),
|
||||
// ^^^^^^^^^^ void
|
||||
},
|
||||
|
@ -8,27 +8,29 @@ mod strings;
|
||||
mod swap2;
|
||||
mod utils;
|
||||
|
||||
use crate::interpreter::wasm;
|
||||
use crate::types::InterfaceType;
|
||||
use crate::vec1::Vec1;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind, InstructionResult, WasmValueNativeCastError},
|
||||
values::{InterfaceValue, NativeType},
|
||||
use crate::errors::{
|
||||
InstructionError, InstructionErrorKind, InstructionResult, WasmValueNativeCastError,
|
||||
};
|
||||
use crate::interpreter::wasm;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::NEVec;
|
||||
pub(crate) use argument_get::argument_get;
|
||||
pub(crate) use arrays::*;
|
||||
pub(crate) use call_core::call_core;
|
||||
pub(crate) use dup::dup;
|
||||
pub(crate) use numbers::*;
|
||||
pub(crate) use records::*;
|
||||
use std::convert::TryFrom;
|
||||
pub(crate) use strings::*;
|
||||
pub(crate) use swap2::swap2;
|
||||
pub(self) use utils::*;
|
||||
|
||||
use fluence_it_types::NativeType;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
pub(self) const ALLOCATE_FUNC_INDEX: u32 = 0;
|
||||
pub(self) const DEALLOCATE_FUNC_INDEX: u32 = 1;
|
||||
|
||||
@ -155,13 +157,13 @@ pub enum Instruction {
|
||||
/// The `array.lift_memory` instruction.
|
||||
ArrayLiftMemory {
|
||||
/// Array value type.
|
||||
value_type: InterfaceType,
|
||||
value_type: IType,
|
||||
},
|
||||
|
||||
/// The `array.lower_memory` instruction.
|
||||
ArrayLowerMemory {
|
||||
/// Array value type.
|
||||
value_type: InterfaceType,
|
||||
value_type: IType,
|
||||
},
|
||||
|
||||
/*
|
||||
@ -198,13 +200,13 @@ pub enum Instruction {
|
||||
}
|
||||
|
||||
/// Just a short helper to map the error of a cast from an
|
||||
/// `InterfaceValue` to a native value.
|
||||
/// `IValue` to a native value.
|
||||
pub(crate) fn to_native<'a, T>(
|
||||
wit_value: &'a InterfaceValue,
|
||||
wit_value: &'a IValue,
|
||||
instruction: Instruction,
|
||||
) -> InstructionResult<T>
|
||||
where
|
||||
T: NativeType + TryFrom<&'a InterfaceValue, Error = WasmValueNativeCastError>,
|
||||
T: NativeType + TryFrom<&'a IValue, Error = WasmValueNativeCastError>,
|
||||
{
|
||||
T::try_from(wit_value)
|
||||
.map_err(|error| InstructionError::new(instruction, InstructionErrorKind::ToNative(error)))
|
||||
@ -220,7 +222,7 @@ pub(crate) fn check_function_signature<
|
||||
>(
|
||||
instance: &'instance Instance,
|
||||
local_import: &LocalImport,
|
||||
values: &[InterfaceValue],
|
||||
values: &[IValue],
|
||||
instruction: Instruction,
|
||||
) -> Result<(), InstructionError>
|
||||
where
|
||||
@ -249,8 +251,8 @@ pub(crate) fn is_value_compatible_to_type<
|
||||
MemoryView,
|
||||
>(
|
||||
instance: &'instance Instance,
|
||||
interface_type: &InterfaceType,
|
||||
interface_value: &InterfaceValue,
|
||||
interface_type: &IType,
|
||||
interface_value: &IValue,
|
||||
instruction: Instruction,
|
||||
) -> Result<(), InstructionError>
|
||||
where
|
||||
@ -261,27 +263,27 @@ where
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
match (&interface_type, interface_value) {
|
||||
(InterfaceType::S8, InterfaceValue::S8(_)) => Ok(()),
|
||||
(InterfaceType::S16, InterfaceValue::S16(_)) => Ok(()),
|
||||
(InterfaceType::S32, InterfaceValue::S32(_)) => Ok(()),
|
||||
(InterfaceType::S64, InterfaceValue::S64(_)) => Ok(()),
|
||||
(InterfaceType::U8, InterfaceValue::U8(_)) => Ok(()),
|
||||
(InterfaceType::U16, InterfaceValue::U16(_)) => Ok(()),
|
||||
(InterfaceType::U32, InterfaceValue::U32(_)) => Ok(()),
|
||||
(InterfaceType::U64, InterfaceValue::U64(_)) => Ok(()),
|
||||
(InterfaceType::I32, InterfaceValue::I32(_)) => Ok(()),
|
||||
(InterfaceType::I64, InterfaceValue::I64(_)) => Ok(()),
|
||||
(InterfaceType::F32, InterfaceValue::F32(_)) => Ok(()),
|
||||
(InterfaceType::F64, InterfaceValue::F64(_)) => Ok(()),
|
||||
(InterfaceType::String, InterfaceValue::String(_)) => Ok(()),
|
||||
(InterfaceType::Array(ty), InterfaceValue::Array(values)) => {
|
||||
(IType::S8, IValue::S8(_)) => Ok(()),
|
||||
(IType::S16, IValue::S16(_)) => Ok(()),
|
||||
(IType::S32, IValue::S32(_)) => Ok(()),
|
||||
(IType::S64, IValue::S64(_)) => Ok(()),
|
||||
(IType::U8, IValue::U8(_)) => Ok(()),
|
||||
(IType::U16, IValue::U16(_)) => Ok(()),
|
||||
(IType::U32, IValue::U32(_)) => Ok(()),
|
||||
(IType::U64, IValue::U64(_)) => Ok(()),
|
||||
(IType::I32, IValue::I32(_)) => Ok(()),
|
||||
(IType::I64, IValue::I64(_)) => Ok(()),
|
||||
(IType::F32, IValue::F32(_)) => Ok(()),
|
||||
(IType::F64, IValue::F64(_)) => Ok(()),
|
||||
(IType::String, IValue::String(_)) => Ok(()),
|
||||
(IType::Array(ty), IValue::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)) => {
|
||||
(IType::Record(ref record_type_id), IValue::Record(record_fields)) => {
|
||||
is_record_fields_compatible_to_type(
|
||||
instance,
|
||||
*record_type_id,
|
||||
@ -311,7 +313,7 @@ pub(crate) fn is_record_fields_compatible_to_type<
|
||||
>(
|
||||
instance: &'instance Instance,
|
||||
record_type_id: u64,
|
||||
record_fields: &[InterfaceValue],
|
||||
record_fields: &[IValue],
|
||||
instruction: Instruction,
|
||||
) -> Result<(), InstructionError>
|
||||
where
|
||||
@ -332,9 +334,9 @@ where
|
||||
return Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::Record(record_type_id),
|
||||
expected_type: IType::Record(record_type_id),
|
||||
// unwrap is safe here - len's been already checked
|
||||
received_value: InterfaceValue::Record(Vec1::new(record_fields.to_vec()).unwrap()),
|
||||
received_value: IValue::Record(NEVec::new(record_fields.to_vec()).unwrap()),
|
||||
},
|
||||
));
|
||||
}
|
||||
@ -359,9 +361,9 @@ pub(crate) mod tests {
|
||||
use std::{cell::Cell, collections::HashMap, convert::TryInto, ops::Deref, rc::Rc};
|
||||
|
||||
pub(crate) struct Export {
|
||||
pub(crate) inputs: Vec<InterfaceType>,
|
||||
pub(crate) outputs: Vec<InterfaceType>,
|
||||
pub(crate) function: fn(arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()>,
|
||||
pub(crate) inputs: Vec<IType>,
|
||||
pub(crate) outputs: Vec<IType>,
|
||||
pub(crate) function: fn(arguments: &[IValue]) -> Result<Vec<IValue>, ()>,
|
||||
}
|
||||
|
||||
impl wasm::structures::Export for Export {
|
||||
@ -373,23 +375,23 @@ pub(crate) mod tests {
|
||||
self.outputs.len()
|
||||
}
|
||||
|
||||
fn arguments(&self) -> &[InterfaceType] {
|
||||
fn arguments(&self) -> &[IType] {
|
||||
&self.inputs
|
||||
}
|
||||
|
||||
fn outputs(&self) -> &[InterfaceType] {
|
||||
fn outputs(&self) -> &[IType] {
|
||||
&self.outputs
|
||||
}
|
||||
|
||||
fn call(&self, arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()> {
|
||||
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
|
||||
(self.function)(arguments)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct LocalImport {
|
||||
pub(crate) inputs: Vec<InterfaceType>,
|
||||
pub(crate) outputs: Vec<InterfaceType>,
|
||||
pub(crate) function: fn(arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()>,
|
||||
pub(crate) inputs: Vec<IType>,
|
||||
pub(crate) outputs: Vec<IType>,
|
||||
pub(crate) function: fn(arguments: &[IValue]) -> Result<Vec<IValue>, ()>,
|
||||
}
|
||||
|
||||
impl wasm::structures::LocalImport for LocalImport {
|
||||
@ -401,15 +403,15 @@ pub(crate) mod tests {
|
||||
self.outputs.len()
|
||||
}
|
||||
|
||||
fn arguments(&self) -> &[InterfaceType] {
|
||||
fn arguments(&self) -> &[IType] {
|
||||
&self.inputs
|
||||
}
|
||||
|
||||
fn outputs(&self) -> &[InterfaceType] {
|
||||
fn outputs(&self) -> &[IType] {
|
||||
&self.outputs
|
||||
}
|
||||
|
||||
fn call(&self, arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()> {
|
||||
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
|
||||
(self.function)(arguments)
|
||||
}
|
||||
}
|
||||
@ -462,13 +464,13 @@ pub(crate) mod tests {
|
||||
hashmap.insert(
|
||||
"sum".into(),
|
||||
Export {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
function: |arguments: &[InterfaceValue]| {
|
||||
inputs: vec![IType::I32, IType::I32],
|
||||
outputs: vec![IType::I32],
|
||||
function: |arguments: &[IValue]| {
|
||||
let a: i32 = (&arguments[0]).try_into().unwrap();
|
||||
let b: i32 = (&arguments[1]).try_into().unwrap();
|
||||
|
||||
Ok(vec![InterfaceValue::I32(a + b)])
|
||||
Ok(vec![IValue::I32(a + b)])
|
||||
},
|
||||
},
|
||||
);
|
||||
@ -481,13 +483,13 @@ pub(crate) mod tests {
|
||||
hashmap.insert(
|
||||
42,
|
||||
LocalImport {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
function: |arguments: &[InterfaceValue]| {
|
||||
inputs: vec![IType::I32, IType::I32],
|
||||
outputs: vec![IType::I32],
|
||||
function: |arguments: &[IValue]| {
|
||||
let a: i32 = (&arguments[0]).try_into().unwrap();
|
||||
let b: i32 = (&arguments[1]).try_into().unwrap();
|
||||
|
||||
Ok(vec![InterfaceValue::I32(a * b)])
|
||||
Ok(vec![IValue::I32(a * b)])
|
||||
},
|
||||
},
|
||||
);
|
||||
@ -495,12 +497,12 @@ pub(crate) mod tests {
|
||||
hashmap.insert(
|
||||
43,
|
||||
LocalImport {
|
||||
inputs: vec![InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
function: |arguments: &[InterfaceValue]| {
|
||||
inputs: vec![IType::I32],
|
||||
outputs: vec![IType::I32],
|
||||
function: |arguments: &[IValue]| {
|
||||
let _size: i32 = (&arguments[0]).try_into().unwrap();
|
||||
|
||||
Ok(vec![InterfaceValue::I32(0)])
|
||||
Ok(vec![IValue::I32(0)])
|
||||
},
|
||||
},
|
||||
);
|
||||
@ -513,27 +515,27 @@ pub(crate) mod tests {
|
||||
fields: vec1![
|
||||
RecordFieldType {
|
||||
name: String::from("field_0"),
|
||||
ty: InterfaceType::I32,
|
||||
ty: IType::I32,
|
||||
},
|
||||
RecordFieldType {
|
||||
name: String::from("field_1"),
|
||||
ty: InterfaceType::Record(RecordType {
|
||||
ty: IType::Record(RecordType {
|
||||
name: String::from("RecordType1"),
|
||||
fields: vec1![
|
||||
RecordFieldType {
|
||||
name: String::from("field_0"),
|
||||
ty: InterfaceType::String,
|
||||
ty: IType::String,
|
||||
},
|
||||
RecordFieldType {
|
||||
name: String::from("field1"),
|
||||
ty: InterfaceType::F32
|
||||
ty: IType::F32
|
||||
}
|
||||
],
|
||||
}),
|
||||
},
|
||||
RecordFieldType {
|
||||
name: String::from("field_2"),
|
||||
ty: InterfaceType::I64,
|
||||
ty: IType::I64,
|
||||
}
|
||||
],
|
||||
})],
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::Instruction,
|
||||
types::InterfaceType,
|
||||
values::InterfaceValue,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
@ -12,17 +12,17 @@ macro_rules! lowering_lifting {
|
||||
$instruction_function_name(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
match runtime.stack.pop1() {
|
||||
Some(InterfaceValue::$from_variant(value)) => {
|
||||
Some(IValue::$from_variant(value)) => {
|
||||
runtime
|
||||
.stack
|
||||
.push({
|
||||
let converted_value = InterfaceValue::$to_variant(value.try_into().map_err(
|
||||
let converted_value = IValue::$to_variant(value.try_into().map_err(
|
||||
|_| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::LoweringLifting {
|
||||
from: InterfaceType::$from_variant,
|
||||
to: InterfaceType::$to_variant
|
||||
from: IType::$from_variant,
|
||||
to: IType::$to_variant
|
||||
},
|
||||
)
|
||||
},
|
||||
@ -37,7 +37,7 @@ macro_rules! lowering_lifting {
|
||||
return Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::$from_variant,
|
||||
expected_type: IType::$from_variant,
|
||||
received_value: wrong_value,
|
||||
}
|
||||
))
|
||||
@ -96,7 +96,7 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_convert_fails =
|
||||
instructions: [Instruction::ArgumentGet { index: 0}, Instruction::S8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(128)],
|
||||
invocation_inputs: [IValue::I32(128)],
|
||||
instance: Instance::new(),
|
||||
error: "`s8.from_i32` failed to cast `I32` to `S8`"
|
||||
);
|
||||
@ -104,7 +104,7 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_type_mismatch =
|
||||
instructions: [Instruction::ArgumentGet { index: 0}, Instruction::S8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
error: "`s8.from_i32` read a value of type `I64` from the stack, but the type `I32` was expected"
|
||||
);
|
||||
@ -112,7 +112,7 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_no_value_on_the_stack =
|
||||
instructions: [Instruction::S8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
error: "`s8.from_i32` needed to read `1` value(s) from the stack, but it doesn't contain enough data"
|
||||
);
|
||||
@ -120,256 +120,256 @@ mod tests {
|
||||
test_executable_instruction!(
|
||||
test_s8_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S8(42)],
|
||||
stack: [IValue::S8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s8_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S8FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S8(42)],
|
||||
stack: [IValue::S8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s16_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S16FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S16(42)],
|
||||
stack: [IValue::S16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s16_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S16FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S16(42)],
|
||||
stack: [IValue::S16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s32_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S32FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S32(42)],
|
||||
stack: [IValue::S32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s32_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S32FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S32(42)],
|
||||
stack: [IValue::S32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s64_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S64FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S64(42)],
|
||||
stack: [IValue::S64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_s64_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S64FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::S64(42)],
|
||||
stack: [IValue::S64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_s8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS8],
|
||||
invocation_inputs: [InterfaceValue::S8(42)],
|
||||
invocation_inputs: [IValue::S8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_s16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS16],
|
||||
invocation_inputs: [InterfaceValue::S16(42)],
|
||||
invocation_inputs: [IValue::S16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_s32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS32],
|
||||
invocation_inputs: [InterfaceValue::S32(42)],
|
||||
invocation_inputs: [IValue::S32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_s64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS64],
|
||||
invocation_inputs: [InterfaceValue::S64(42)],
|
||||
invocation_inputs: [IValue::S64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_s8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS8],
|
||||
invocation_inputs: [InterfaceValue::S8(42)],
|
||||
invocation_inputs: [IValue::S8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
stack: [IValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_s16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS16],
|
||||
invocation_inputs: [InterfaceValue::S16(42)],
|
||||
invocation_inputs: [IValue::S16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
stack: [IValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_s32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS32],
|
||||
invocation_inputs: [InterfaceValue::S32(42)],
|
||||
invocation_inputs: [IValue::S32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
stack: [IValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_s64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS64],
|
||||
invocation_inputs: [InterfaceValue::S64(42)],
|
||||
invocation_inputs: [IValue::S64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
stack: [IValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u8_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U8FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U8(42)],
|
||||
stack: [IValue::U8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u8_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U8FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U8(42)],
|
||||
stack: [IValue::U8(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u16_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U16FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U16(42)],
|
||||
stack: [IValue::U16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u16_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U16FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U16(42)],
|
||||
stack: [IValue::U16(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u32_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U32FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U32(42)],
|
||||
stack: [IValue::U32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u32_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U32FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U32(42)],
|
||||
stack: [IValue::U32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u64_from_i32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U64FromI32],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U64(42)],
|
||||
stack: [IValue::U64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_u64_from_i64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U64FromI64],
|
||||
invocation_inputs: [InterfaceValue::I64(42)],
|
||||
invocation_inputs: [IValue::I64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::U64(42)],
|
||||
stack: [IValue::U64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_u8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU8],
|
||||
invocation_inputs: [InterfaceValue::U8(42)],
|
||||
invocation_inputs: [IValue::U8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_u16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU16],
|
||||
invocation_inputs: [InterfaceValue::U16(42)],
|
||||
invocation_inputs: [IValue::U16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_u32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU32],
|
||||
invocation_inputs: [InterfaceValue::U32(42)],
|
||||
invocation_inputs: [IValue::U32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i32_from_u64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU64],
|
||||
invocation_inputs: [InterfaceValue::U64(42)],
|
||||
invocation_inputs: [IValue::U64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(42)],
|
||||
stack: [IValue::I32(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_u8 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU8],
|
||||
invocation_inputs: [InterfaceValue::U8(42)],
|
||||
invocation_inputs: [IValue::U8(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
stack: [IValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_u16 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU16],
|
||||
invocation_inputs: [InterfaceValue::U16(42)],
|
||||
invocation_inputs: [IValue::U16(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
stack: [IValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_u32 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU32],
|
||||
invocation_inputs: [InterfaceValue::U32(42)],
|
||||
invocation_inputs: [IValue::U32(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
stack: [IValue::I64(42)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
test_i64_from_u64 =
|
||||
instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU64],
|
||||
invocation_inputs: [InterfaceValue::U64(42)],
|
||||
invocation_inputs: [IValue::U64(42)],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I64(42)],
|
||||
stack: [IValue::I64(42)],
|
||||
);
|
||||
}
|
||||
|
@ -2,18 +2,19 @@ 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::IRecordType;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::NEVec;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::Instruction,
|
||||
types::{InterfaceType, RecordType},
|
||||
values::InterfaceValue,
|
||||
vec1::Vec1,
|
||||
};
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
/*
|
||||
/// Build an `InterfaceValue::Record` based on values on the stack.
|
||||
/// Build an `IValue::Record` based on values on the stack.
|
||||
///
|
||||
/// To fill a record, every field `field_1` to `field_n` must get its
|
||||
/// value from the stack with `value_1` to `value_n`. It is not
|
||||
@ -27,14 +28,14 @@ use std::convert::TryInto;
|
||||
/// is possible to access to last positions). So a `VecDeque` type is
|
||||
/// used: it is a double-ended queue.
|
||||
fn record_lift_(
|
||||
stack: &mut Stack<InterfaceValue>,
|
||||
stack: &mut Stack<IValue>,
|
||||
record_type: &RecordType,
|
||||
) -> Result<InterfaceValue, InstructionErrorKind> {
|
||||
) -> Result<IValue, InstructionErrorKind> {
|
||||
let length = record_type.fields.len();
|
||||
let mut values = VecDeque::with_capacity(length);
|
||||
for field in record_type.fields.iter().rev() {
|
||||
match field {
|
||||
InterfaceType::Record(record_type) => {
|
||||
IType::Record(record_type) => {
|
||||
values.push_front(record_lift_(stack, &record_type)?)
|
||||
}
|
||||
ty => {
|
||||
@ -50,8 +51,8 @@ fn record_lift_(
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(InterfaceValue::Record(
|
||||
Vec1::new(values.into_iter().collect())
|
||||
Ok(IValue::Record(
|
||||
NEVec::new(values.into_iter().collect())
|
||||
.expect("Record must have at least one field, zero given"),
|
||||
))
|
||||
}
|
||||
@ -101,10 +102,10 @@ where
|
||||
|
||||
pub(super) fn record_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
record_type: &RecordType,
|
||||
record_type: &IRecordType,
|
||||
offset: usize,
|
||||
instruction: Instruction,
|
||||
) -> Result<InterfaceValue, InstructionError>
|
||||
) -> Result<IValue, InstructionError>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
LocalImport: crate::interpreter::wasm::structures::LocalImport,
|
||||
@ -113,12 +114,12 @@ where
|
||||
Instance: crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>
|
||||
+ 'instance,
|
||||
{
|
||||
fn record_size(record_type: &RecordType) -> usize {
|
||||
fn record_size(record_type: &IRecordType) -> usize {
|
||||
let mut record_size = 0;
|
||||
|
||||
for field_type in record_type.fields.iter() {
|
||||
let params_count = match field_type.ty {
|
||||
InterfaceType::String | InterfaceType::Array(_) => 2,
|
||||
IType::String | IType::Array(_) => 2,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
@ -140,42 +141,42 @@ where
|
||||
for field in (*record_type.fields).iter() {
|
||||
let value = data[field_id];
|
||||
match &field.ty {
|
||||
InterfaceType::S8 => {
|
||||
values.push(InterfaceValue::S8(value as _));
|
||||
IType::S8 => {
|
||||
values.push(IValue::S8(value as _));
|
||||
}
|
||||
InterfaceType::S16 => {
|
||||
values.push(InterfaceValue::S16(value as _));
|
||||
IType::S16 => {
|
||||
values.push(IValue::S16(value as _));
|
||||
}
|
||||
InterfaceType::S32 => {
|
||||
values.push(InterfaceValue::S32(value as _));
|
||||
IType::S32 => {
|
||||
values.push(IValue::S32(value as _));
|
||||
}
|
||||
InterfaceType::S64 => {
|
||||
values.push(InterfaceValue::S64(value as _));
|
||||
IType::S64 => {
|
||||
values.push(IValue::S64(value as _));
|
||||
}
|
||||
InterfaceType::I32 => {
|
||||
values.push(InterfaceValue::I32(value as _));
|
||||
IType::I32 => {
|
||||
values.push(IValue::I32(value as _));
|
||||
}
|
||||
InterfaceType::I64 => {
|
||||
values.push(InterfaceValue::I64(value as _));
|
||||
IType::I64 => {
|
||||
values.push(IValue::I64(value as _));
|
||||
}
|
||||
InterfaceType::U8 => {
|
||||
values.push(InterfaceValue::U8(value as _));
|
||||
IType::U8 => {
|
||||
values.push(IValue::U8(value as _));
|
||||
}
|
||||
InterfaceType::U16 => {
|
||||
values.push(InterfaceValue::U16(value as _));
|
||||
IType::U16 => {
|
||||
values.push(IValue::U16(value as _));
|
||||
}
|
||||
InterfaceType::U32 => {
|
||||
values.push(InterfaceValue::U32(value as _));
|
||||
IType::U32 => {
|
||||
values.push(IValue::U32(value as _));
|
||||
}
|
||||
InterfaceType::U64 => {
|
||||
values.push(InterfaceValue::U64(value as _));
|
||||
IType::U64 => {
|
||||
values.push(IValue::U64(value as _));
|
||||
}
|
||||
InterfaceType::F32 => {
|
||||
values.push(InterfaceValue::F32(value as _));
|
||||
IType::F32 => {
|
||||
values.push(IValue::F32(value as _));
|
||||
}
|
||||
InterfaceType::F64 => values.push(InterfaceValue::F64(f64::from_bits(value))),
|
||||
InterfaceType::Anyref => {}
|
||||
InterfaceType::String => {
|
||||
IType::F64 => values.push(IValue::F64(f64::from_bits(value))),
|
||||
IType::Anyref => {}
|
||||
IType::String => {
|
||||
let string_offset = value;
|
||||
field_id += 1;
|
||||
let string_size = data[field_id];
|
||||
@ -190,12 +191,12 @@ where
|
||||
|
||||
// TODO: check
|
||||
let string = String::from_utf8(string_mem).unwrap();
|
||||
values.push(InterfaceValue::String(string));
|
||||
values.push(IValue::String(string));
|
||||
} else {
|
||||
values.push(InterfaceValue::String(String::new()));
|
||||
values.push(IValue::String(String::new()));
|
||||
}
|
||||
}
|
||||
InterfaceType::Array(ty) => {
|
||||
IType::Array(ty) => {
|
||||
let array_offset = value;
|
||||
field_id += 1;
|
||||
let array_size = data[field_id];
|
||||
@ -208,12 +209,12 @@ where
|
||||
array_size as _,
|
||||
instruction.clone(),
|
||||
)?;
|
||||
values.push(InterfaceValue::Array(array));
|
||||
values.push(IValue::Array(array));
|
||||
} else {
|
||||
values.push(InterfaceValue::Array(vec![]));
|
||||
values.push(IValue::Array(vec![]));
|
||||
}
|
||||
}
|
||||
InterfaceType::Record(record_type_id) => {
|
||||
IType::Record(record_type_id) => {
|
||||
let offset = value;
|
||||
|
||||
let record_type = instance.wit_record_by_id(*record_type_id).ok_or_else(|| {
|
||||
@ -238,8 +239,8 @@ where
|
||||
|
||||
super::deallocate(instance, instruction, offset as _, size as _)?;
|
||||
|
||||
Ok(InterfaceValue::Record(
|
||||
Vec1::new(values.into_iter().collect())
|
||||
Ok(IValue::Record(
|
||||
NEVec::new(values.into_iter().collect())
|
||||
.expect("Record must have at least one field, zero given"),
|
||||
))
|
||||
}
|
||||
@ -301,7 +302,7 @@ where
|
||||
pub(super) fn record_lower_memory_<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &mut Instance,
|
||||
instruction: Instruction,
|
||||
values: Vec1<InterfaceValue>,
|
||||
values: NEVec<IValue>,
|
||||
) -> Result<i32, InstructionError>
|
||||
where
|
||||
Export: crate::interpreter::wasm::structures::Export,
|
||||
@ -315,19 +316,19 @@ where
|
||||
|
||||
for value in values.into_vec() {
|
||||
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) => {
|
||||
IValue::S8(value) => result.push(value as _),
|
||||
IValue::S16(value) => result.push(value as _),
|
||||
IValue::S32(value) => result.push(value as _),
|
||||
IValue::S64(value) => result.push(value as _),
|
||||
IValue::U8(value) => result.push(value as _),
|
||||
IValue::U16(value) => result.push(value as _),
|
||||
IValue::U32(value) => result.push(value as _),
|
||||
IValue::U64(value) => result.push(value as _),
|
||||
IValue::I32(value) => result.push(value as _),
|
||||
IValue::I64(value) => result.push(value as _),
|
||||
IValue::F32(value) => result.push(value as _),
|
||||
IValue::F64(value) => result.push(value.to_bits()),
|
||||
IValue::String(value) => {
|
||||
let string_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?
|
||||
} else {
|
||||
@ -338,7 +339,7 @@ where
|
||||
result.push(value.len() as _);
|
||||
}
|
||||
|
||||
InterfaceValue::Array(values) => {
|
||||
IValue::Array(values) => {
|
||||
let (offset, size) = if !values.is_empty() {
|
||||
super::array_lower_memory_(instance, instruction.clone(), values)?
|
||||
} else {
|
||||
@ -349,7 +350,7 @@ where
|
||||
result.push(size as _);
|
||||
}
|
||||
|
||||
InterfaceValue::Record(values) => {
|
||||
IValue::Record(values) => {
|
||||
let record_ptr = record_lower_memory_(instance, instruction.clone(), values)?;
|
||||
|
||||
result.push(record_ptr as _);
|
||||
@ -382,7 +383,7 @@ where
|
||||
let instance = &mut runtime.wasm_instance;
|
||||
|
||||
match runtime.stack.pop1() {
|
||||
Some(InterfaceValue::Record(record_fields)) => {
|
||||
Some(IValue::Record(record_fields)) => {
|
||||
is_record_fields_compatible_to_type(
|
||||
&**instance,
|
||||
record_type_id,
|
||||
@ -396,14 +397,14 @@ where
|
||||
record_lower_memory_(*instance, instruction.clone(), record_fields)?;
|
||||
|
||||
log::debug!("record.lower_memory: pushing {} on the stack", offset);
|
||||
runtime.stack.push(InterfaceValue::I32(offset));
|
||||
runtime.stack.push(IValue::I32(offset));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Some(value) => Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::Record(record_type_id),
|
||||
expected_type: IType::Record(record_type_id),
|
||||
received_value: value,
|
||||
},
|
||||
)),
|
||||
@ -452,7 +453,7 @@ where
|
||||
}
|
||||
};
|
||||
match runtime.stack.pop1() {
|
||||
Some(InterfaceValue::Record(record_values))
|
||||
Some(IValue::Record(record_values))
|
||||
if record_type == &(&*record_values).into() =>
|
||||
{
|
||||
let values = FlattenIValueIterator::new(&record_values);
|
||||
@ -464,7 +465,7 @@ where
|
||||
Some(value) => Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::Record(record_type.clone()),
|
||||
expected_type: IType::Record(record_type.clone()),
|
||||
received_type: (&value).into(),
|
||||
},
|
||||
)),
|
||||
|
@ -1,9 +1,9 @@
|
||||
use super::to_native;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::Instruction,
|
||||
types::InterfaceType,
|
||||
values::InterfaceValue,
|
||||
};
|
||||
use std::{cell::Cell, convert::TryInto};
|
||||
|
||||
@ -39,7 +39,7 @@ executable_instruction!(
|
||||
let memory_view = memory.view();
|
||||
|
||||
if length == 0 {
|
||||
runtime.stack.push(InterfaceValue::String("".into()));
|
||||
runtime.stack.push(IValue::String("".into()));
|
||||
|
||||
return Ok(())
|
||||
}
|
||||
@ -63,7 +63,7 @@ executable_instruction!(
|
||||
.map_err(|error| InstructionError::new(instruction.clone(), InstructionErrorKind::String(error)))?;
|
||||
|
||||
log::debug!("string.lift_memory: pushing {:?} on the stack", string);
|
||||
runtime.stack.push(InterfaceValue::String(string));
|
||||
runtime.stack.push(IValue::String(string));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -110,8 +110,8 @@ executable_instruction!(
|
||||
}
|
||||
|
||||
log::debug!("string.lower_memory: pushing {}, {} on the stack", string_pointer, string_length);
|
||||
runtime.stack.push(InterfaceValue::I32(string_pointer as i32));
|
||||
runtime.stack.push(InterfaceValue::I32(string_length));
|
||||
runtime.stack.push(IValue::I32(string_pointer as i32));
|
||||
runtime.stack.push(IValue::I32(string_length));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -122,11 +122,11 @@ executable_instruction!(
|
||||
string_size(instruction: Instruction) -> _ {
|
||||
move |runtime| -> _ {
|
||||
match runtime.stack.pop1() {
|
||||
Some(InterfaceValue::String(string)) => {
|
||||
Some(IValue::String(string)) => {
|
||||
let length = string.len() as i32;
|
||||
|
||||
log::debug!("string.size: pushing {} on the stack", length);
|
||||
runtime.stack.push(InterfaceValue::I32(length));
|
||||
runtime.stack.push(IValue::I32(length));
|
||||
|
||||
Ok(())
|
||||
},
|
||||
@ -134,7 +134,7 @@ executable_instruction!(
|
||||
Some(value) => Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: InterfaceType::String,
|
||||
expected_type: IType::String,
|
||||
received_value: (&value).clone(),
|
||||
},
|
||||
)),
|
||||
@ -158,16 +158,16 @@ mod tests {
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
IValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(13),
|
||||
IValue::I32(13),
|
||||
// ^^^^^^^ length
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new("Hello, World!".as_bytes().iter().map(|u| Cell::new(*u)).collect()),
|
||||
..Default::default()
|
||||
},
|
||||
stack: [InterfaceValue::String("Hello, World!".into())],
|
||||
stack: [IValue::String("Hello, World!".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
@ -178,14 +178,14 @@ mod tests {
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
InterfaceValue::I32(0),
|
||||
IValue::I32(0),
|
||||
IValue::I32(0),
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new(vec![]),
|
||||
..Default::default()
|
||||
},
|
||||
stack: [InterfaceValue::String("".into())],
|
||||
stack: [IValue::String("".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
@ -196,8 +196,8 @@ mod tests {
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(-42),
|
||||
InterfaceValue::I32(13),
|
||||
IValue::I32(-42),
|
||||
IValue::I32(13),
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new("Hello!".as_bytes().iter().map(|u| Cell::new(*u)).collect()),
|
||||
@ -214,8 +214,8 @@ mod tests {
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
InterfaceValue::I32(-1),
|
||||
IValue::I32(0),
|
||||
IValue::I32(-1),
|
||||
],
|
||||
instance: Instance {
|
||||
memory: Memory::new("Hello!".as_bytes().iter().map(|u| Cell::new(*u)).collect()),
|
||||
@ -232,9 +232,9 @@ mod tests {
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
IValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(13),
|
||||
IValue::I32(13),
|
||||
// ^^^^^^^ length is too long
|
||||
],
|
||||
instance: Instance {
|
||||
@ -252,9 +252,9 @@ mod tests {
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
IValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(4),
|
||||
IValue::I32(4),
|
||||
// ^^^^^^ length is too long
|
||||
],
|
||||
instance: Instance {
|
||||
@ -272,8 +272,8 @@ mod tests {
|
||||
// ^^^^^^^^^^^^^^^^ `string.lift_memory` expects 2 values on the stack, only one is present.
|
||||
],
|
||||
invocation_inputs: [
|
||||
InterfaceValue::I32(0),
|
||||
InterfaceValue::I32(13),
|
||||
IValue::I32(0),
|
||||
IValue::I32(13),
|
||||
],
|
||||
instance: Instance::new(),
|
||||
error: r#"`string.lift_memory` needed to read `2` value(s) from the stack, but it doesn't contain enough data"#,
|
||||
@ -289,12 +289,12 @@ mod tests {
|
||||
Instruction::StringLowerMemory,
|
||||
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
invocation_inputs: [IValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
stack: [
|
||||
InterfaceValue::I32(0),
|
||||
IValue::I32(0),
|
||||
// ^^^^^^ pointer
|
||||
InterfaceValue::I32(13),
|
||||
IValue::I32(13),
|
||||
// ^^^^^^^ length
|
||||
]
|
||||
);
|
||||
@ -309,9 +309,9 @@ mod tests {
|
||||
Instruction::StringLowerMemory,
|
||||
Instruction::StringLiftMemory,
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
invocation_inputs: [IValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::String("Hello, World!".into())],
|
||||
stack: [IValue::String("Hello, World!".into())],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
@ -330,9 +330,9 @@ mod tests {
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringSize,
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::String("Hello, World!".into())],
|
||||
invocation_inputs: [IValue::String("Hello, World!".into())],
|
||||
instance: Instance::new(),
|
||||
stack: [InterfaceValue::I32(13)],
|
||||
stack: [IValue::I32(13)],
|
||||
);
|
||||
|
||||
test_executable_instruction!(
|
||||
@ -351,7 +351,7 @@ mod tests {
|
||||
Instruction::ArgumentGet { index: 0 },
|
||||
Instruction::StringSize,
|
||||
],
|
||||
invocation_inputs: [InterfaceValue::I32(42)],
|
||||
invocation_inputs: [IValue::I32(42)],
|
||||
instance: Instance::new(),
|
||||
error: r#"`string.size` read a value of type `I32` from the stack, but the type `String` was expected"#,
|
||||
);
|
||||
|
@ -4,11 +4,11 @@ use crate::interpreter::wasm;
|
||||
use crate::interpreter::wasm::structures::{FunctionIndex, TypedIndex};
|
||||
|
||||
use crate::interpreter::instructions::to_native;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::Instruction,
|
||||
types::InterfaceType,
|
||||
values::InterfaceValue,
|
||||
};
|
||||
|
||||
pub(super) fn read_from_instance_mem<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
@ -115,14 +115,14 @@ where
|
||||
instance,
|
||||
ALLOCATE_FUNC_INDEX,
|
||||
instruction.clone(),
|
||||
vec![InterfaceValue::I32(size as _)],
|
||||
vec![IValue::I32(size as _)],
|
||||
)?;
|
||||
if values.len() != 1 {
|
||||
return Err(InstructionError::new(
|
||||
instruction,
|
||||
InstructionErrorKind::LocalOrImportSignatureMismatch {
|
||||
function_index: ALLOCATE_FUNC_INDEX,
|
||||
expected: (vec![InterfaceType::I32], vec![]),
|
||||
expected: (vec![IType::I32], vec![]),
|
||||
received: (vec![], vec![]),
|
||||
},
|
||||
));
|
||||
@ -147,7 +147,7 @@ where
|
||||
instance,
|
||||
DEALLOCATE_FUNC_INDEX,
|
||||
instruction,
|
||||
vec![InterfaceValue::I32(mem_ptr), InterfaceValue::I32(size)],
|
||||
vec![IValue::I32(mem_ptr), IValue::I32(size)],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@ -157,8 +157,8 @@ fn call_core<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
function_index: u32,
|
||||
instruction: Instruction,
|
||||
inputs: Vec<InterfaceValue>,
|
||||
) -> Result<Vec<InterfaceValue>, InstructionError>
|
||||
inputs: Vec<IValue>,
|
||||
) -> Result<Vec<IValue>, InstructionError>
|
||||
where
|
||||
Export: wasm::structures::Export + 'instance,
|
||||
LocalImport: wasm::structures::LocalImport + 'instance,
|
||||
|
@ -4,10 +4,8 @@ mod instructions;
|
||||
pub mod stack;
|
||||
pub mod wasm;
|
||||
|
||||
use crate::{
|
||||
errors::{InstructionResult, InterpreterResult},
|
||||
values::InterfaceValue,
|
||||
};
|
||||
use crate::errors::{InstructionResult, InterpreterResult};
|
||||
use crate::IValue;
|
||||
pub use instructions::Instruction;
|
||||
use stack::Stack;
|
||||
use std::{convert::TryFrom, marker::PhantomData};
|
||||
@ -24,10 +22,10 @@ where
|
||||
{
|
||||
/// The invocation inputs are all the arguments received by an
|
||||
/// adapter.
|
||||
invocation_inputs: &'invocation [InterfaceValue],
|
||||
invocation_inputs: &'invocation [IValue],
|
||||
|
||||
/// Each runtime (so adapter) has its own stack instance.
|
||||
stack: Stack<InterfaceValue>,
|
||||
stack: Stack<IValue>,
|
||||
|
||||
/// The WebAssembly module instance. It is used by adapter's
|
||||
/// instructions.
|
||||
@ -68,8 +66,8 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
|
||||
/// stack::Stackable,
|
||||
/// Instruction, Interpreter,
|
||||
/// },
|
||||
/// types::InterfaceType,
|
||||
/// values::InterfaceValue,
|
||||
/// types::IType,
|
||||
/// values::IValue,
|
||||
/// };
|
||||
///
|
||||
/// // 1. Creates an interpreter from a set of instructions. They will
|
||||
@ -83,7 +81,7 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
|
||||
/// .unwrap();
|
||||
///
|
||||
/// // 2. Defines the arguments of the adapter.
|
||||
/// let invocation_inputs = vec![InterfaceValue::I32(3), InterfaceValue::I32(4)];
|
||||
/// let invocation_inputs = vec![IValue::I32(3), IValue::I32(4)];
|
||||
///
|
||||
/// // 3. Creates a WebAssembly instance.
|
||||
/// let mut instance = Instance {
|
||||
@ -94,17 +92,17 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
|
||||
/// 42,
|
||||
/// LocalImport {
|
||||
/// // Defines the argument types of the function.
|
||||
/// inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
/// inputs: vec![IType::I32, IType::I32],
|
||||
///
|
||||
/// // Defines the result types.
|
||||
/// outputs: vec![InterfaceType::I32],
|
||||
/// outputs: vec![IType::I32],
|
||||
///
|
||||
/// // Defines the function implementation.
|
||||
/// function: |arguments: &[InterfaceValue]| {
|
||||
/// function: |arguments: &[IValue]| {
|
||||
/// let a: i32 = (&arguments[0]).try_into().unwrap();
|
||||
/// let b: i32 = (&arguments[1]).try_into().unwrap();
|
||||
///
|
||||
/// Ok(vec![InterfaceValue::I32(a + b)])
|
||||
/// Ok(vec![IValue::I32(a + b)])
|
||||
/// },
|
||||
/// },
|
||||
/// );
|
||||
@ -120,7 +118,7 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
|
||||
/// let stack = run.unwrap();
|
||||
///
|
||||
/// // 5. Read the stack to get the result.
|
||||
/// assert_eq!(stack.as_slice(), &[InterfaceValue::I32(7)]);
|
||||
/// assert_eq!(stack.as_slice(), &[IValue::I32(7)]);
|
||||
/// ```
|
||||
pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
|
||||
where
|
||||
@ -158,9 +156,9 @@ where
|
||||
/// returns the stack.
|
||||
pub fn run(
|
||||
&self,
|
||||
invocation_inputs: &[InterfaceValue],
|
||||
invocation_inputs: &[IValue],
|
||||
wasm_instance: &mut Instance,
|
||||
) -> InterpreterResult<Stack<InterfaceValue>> {
|
||||
) -> InterpreterResult<Stack<IValue>> {
|
||||
let mut runtime = Runtime {
|
||||
invocation_inputs,
|
||||
stack: Stack::new(),
|
||||
|
@ -1,8 +1,9 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::ast::FunctionArg;
|
||||
use crate::types::RecordType;
|
||||
use crate::{types::InterfaceType, values::InterfaceValue};
|
||||
use crate::IRecordType;
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use std::rc::Rc;
|
||||
use std::{cell::Cell, ops::Deref};
|
||||
|
||||
@ -47,8 +48,8 @@ pub trait Export {
|
||||
fn inputs_cardinality(&self) -> usize;
|
||||
fn outputs_cardinality(&self) -> usize;
|
||||
fn arguments(&self) -> &[FunctionArg];
|
||||
fn outputs(&self) -> &[InterfaceType];
|
||||
fn call(&self, arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()>;
|
||||
fn outputs(&self) -> &[IType];
|
||||
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()>;
|
||||
}
|
||||
|
||||
pub trait LocalImport {
|
||||
@ -56,8 +57,8 @@ pub trait LocalImport {
|
||||
fn inputs_cardinality(&self) -> usize;
|
||||
fn outputs_cardinality(&self) -> usize;
|
||||
fn arguments(&self) -> &[FunctionArg];
|
||||
fn outputs(&self) -> &[InterfaceType];
|
||||
fn call(&self, arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()>;
|
||||
fn outputs(&self) -> &[IType];
|
||||
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()>;
|
||||
}
|
||||
|
||||
pub trait MemoryView: Deref<Target = [Cell<u8>]> {}
|
||||
@ -79,7 +80,7 @@ where
|
||||
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 wit_record_by_id(&self, index: u64) -> Option<&Rc<RecordType>>;
|
||||
fn wit_record_by_id(&self, index: u64) -> Option<&Rc<IRecordType>>;
|
||||
}
|
||||
|
||||
impl Export for () {
|
||||
@ -99,11 +100,11 @@ impl Export for () {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn outputs(&self) -> &[InterfaceType] {
|
||||
fn outputs(&self) -> &[IType] {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn call(&self, _arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()> {
|
||||
fn call(&self, _arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
@ -125,11 +126,11 @@ impl LocalImport for () {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn outputs(&self) -> &[InterfaceType] {
|
||||
fn outputs(&self) -> &[IType] {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn call(&self, _arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()> {
|
||||
fn call(&self, _arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
@ -171,7 +172,7 @@ where
|
||||
None
|
||||
}
|
||||
|
||||
fn wit_record_by_id(&self, _index: u64) -> Option<&Rc<RecordType>> {
|
||||
fn wit_record_by_id(&self, _index: u64) -> Option<&Rc<IRecordType>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -64,13 +64,14 @@ pub mod interpreter;
|
||||
mod serde;
|
||||
mod values;
|
||||
|
||||
pub use fluence_it_types::vec1::Vec1;
|
||||
pub use fluence_it_types::ne_vec::NEVec;
|
||||
pub use fluence_it_types::IRecordFieldType;
|
||||
pub use fluence_it_types::IRecordType;
|
||||
pub use fluence_it_types::IType;
|
||||
pub use fluence_it_types::IValue;
|
||||
|
||||
pub(crate) struct ITypeImpl(pub IType);
|
||||
pub(crate) struct RecordTypeImpl(pub IRecordType);
|
||||
pub(crate) struct RecordFieldTypeImpl(pub IRecordFieldType);
|
||||
pub(crate) struct IValueImpl(pub IValue);
|
||||
#[cfg(feature = "serde")]
|
||||
pub use crate::serde::de::from_interface_values;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
pub use crate::serde::ser::to_interface_value;
|
||||
|
@ -14,13 +14,13 @@ macro_rules! vec1 {
|
||||
|
||||
($item:expr; $length:expr) => {
|
||||
{
|
||||
crate::vec1::Vec1::new(vec![$item; $length]).unwrap()
|
||||
crate::vec1::NEVec::new(vec![$item; $length]).unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
($($item:expr),+ $(,)?) => {
|
||||
{
|
||||
crate::vec1::Vec1::new(vec![$($item),*]).unwrap()
|
||||
crate::vec1::NEVec::new(vec![$($item),*]).unwrap()
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -104,8 +104,8 @@ macro_rules! test_executable_instruction {
|
||||
stack::Stackable,
|
||||
Instruction, Interpreter,
|
||||
},
|
||||
types::InterfaceType,
|
||||
values::InterfaceValue,
|
||||
types::IType,
|
||||
values::IValue,
|
||||
};
|
||||
use std::{cell::Cell, collections::HashMap, convert::TryInto};
|
||||
|
||||
@ -146,8 +146,8 @@ macro_rules! test_executable_instruction {
|
||||
stack::Stackable,
|
||||
Instruction, Interpreter,
|
||||
},
|
||||
types::InterfaceType,
|
||||
values::InterfaceValue,
|
||||
types::IType,
|
||||
values::IValue,
|
||||
};
|
||||
use std::{cell::Cell, collections::HashMap, convert::TryInto};
|
||||
|
||||
|
@ -33,9 +33,9 @@ use std::{
|
||||
/// y: f32,
|
||||
/// };
|
||||
///
|
||||
/// let values = vec![IValue::Record(Vec1::new(vec![
|
||||
/// let values = vec![IValue::Record(NEVec::new(vec![
|
||||
/// IValue::String("abc".to_string()),
|
||||
/// IValue::Record(Vec1::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()),
|
||||
/// IValue::Record(NEVec::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()),
|
||||
/// IValue::F32(3.),
|
||||
/// ]).unwrap())];
|
||||
/// let t = from_interface_values::<T>(&values).unwrap();
|
||||
@ -62,14 +62,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// The deserializer. The iterator iterates over `InterfaceValue`s,
|
||||
/// The deserializer. The iterator iterates over `IValue`s,
|
||||
/// all flatten, see `FlattenIValueIterator`.
|
||||
struct Deserializer<'de> {
|
||||
iterator: Peekable<FlattenIValueIterator<'de>>,
|
||||
}
|
||||
|
||||
impl<'de> Deserializer<'de> {
|
||||
pub fn new(input: &'de [InterfaceValue]) -> Deserializer<'de> {
|
||||
pub fn new(input: &'de [IValue]) -> Deserializer<'de> {
|
||||
Deserializer {
|
||||
iterator: FlattenIValueIterator::new(input).peekable(),
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
//! Provides a serializer from Rust value to WIT values.
|
||||
|
||||
use crate::IValue;
|
||||
use crate::IValueImpl;
|
||||
use crate::Vec1;
|
||||
use crate::NEVec;
|
||||
use serde::{ser, Serialize};
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
@ -39,9 +38,9 @@ use std::fmt::{self, Display};
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// to_interface_value(&input).unwrap(),
|
||||
/// IValue::Record(Vec1::new(vec![
|
||||
/// IValue::Record(NEVec::new(vec![
|
||||
/// IValue::String("abc".to_string()),
|
||||
/// IValue::Record(Vec1::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()),
|
||||
/// IValue::Record(NEVec::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()),
|
||||
/// IValue::F32(3.),
|
||||
/// ]).unwrap()),
|
||||
/// );
|
||||
@ -51,7 +50,6 @@ where
|
||||
T: Serialize,
|
||||
{
|
||||
let mut serializer = Serializer::new();
|
||||
let value = ValueImpl(value);
|
||||
value.serialize(&mut serializer)?;
|
||||
|
||||
if serializer.values.len() != 1 {
|
||||
@ -64,14 +62,14 @@ where
|
||||
} else {
|
||||
let first_value = first_values.pop().unwrap(); // this `unwrap` is safe because we are sure the length is 1.
|
||||
|
||||
Ok(first_value.0)
|
||||
Ok(first_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The serializer.
|
||||
struct Serializer {
|
||||
values: Vec<Vec<IValueImpl>>,
|
||||
values: Vec<Vec<IValue>>,
|
||||
}
|
||||
|
||||
impl Serializer {
|
||||
@ -81,7 +79,7 @@ impl Serializer {
|
||||
}
|
||||
}
|
||||
|
||||
fn last(&mut self) -> &mut Vec<IValueImpl> {
|
||||
fn last(&mut self) -> &mut Vec<IValue> {
|
||||
self.values.last_mut().unwrap()
|
||||
}
|
||||
|
||||
@ -89,7 +87,7 @@ impl Serializer {
|
||||
self.values.push(Vec::with_capacity(capacity));
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Result<Vec<IValueImpl>, SerializeError> {
|
||||
fn pop(&mut self) -> Result<Vec<IValue>, SerializeError> {
|
||||
// The first `vec` contains the final result. It is forbidden
|
||||
// to `pop` it as is.
|
||||
if self.values.len() < 2 {
|
||||
@ -364,10 +362,7 @@ impl<'a> ser::SerializeSeq for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
|
||||
|
||||
let record = IValue::Array(values);
|
||||
let record = IValueImpl(record);
|
||||
let record = IValue::Array(self.pop()?);
|
||||
self.last().push(record);
|
||||
|
||||
Ok(())
|
||||
@ -402,11 +397,9 @@ impl<'a> ser::SerializeTupleStruct for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
|
||||
|
||||
let record =
|
||||
IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?);
|
||||
let record = ValueImpl(record);
|
||||
let record = IValue::Record(
|
||||
NEVec::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
|
||||
);
|
||||
self.last().push(record);
|
||||
|
||||
Ok(())
|
||||
@ -448,11 +441,9 @@ impl<'a> ser::SerializeMap for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
|
||||
|
||||
let record =
|
||||
IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?);
|
||||
let record = ValueImpl(record);
|
||||
let record = IValue::Record(
|
||||
NEVec::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
|
||||
);
|
||||
self.last().push(record);
|
||||
|
||||
Ok(())
|
||||
@ -471,11 +462,9 @@ impl<'a> ser::SerializeStruct for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
|
||||
|
||||
let record =
|
||||
IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?);
|
||||
let record = ValueImpl(record);
|
||||
let record = IValue::Record(
|
||||
NEVec::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
|
||||
);
|
||||
self.last().push(record);
|
||||
|
||||
Ok(())
|
||||
|
@ -1,59 +1,10 @@
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::IValueImpl;
|
||||
use crate::{errors::WasmValueNativeCastError, types::IType, vec1::Vec1};
|
||||
use std::{convert::TryFrom, slice::Iter};
|
||||
|
||||
use std::slice::Iter;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
pub use crate::serde::{de::from_interface_values, ser::to_interface_value};
|
||||
|
||||
/// Represents a native type supported by WIT.
|
||||
pub trait NativeType {
|
||||
/// The associated interface type that maps to the native type.
|
||||
const INTERFACE_TYPE: IType;
|
||||
}
|
||||
|
||||
macro_rules! native {
|
||||
($native_type:ty, $variant:ident) => {
|
||||
impl NativeType for $native_type {
|
||||
const INTERFACE_TYPE: IType = IType::$variant;
|
||||
}
|
||||
|
||||
impl From<$native_type> for IValueImpl {
|
||||
fn from(n: $native_type) -> Self {
|
||||
let ivalue = IValue::$variant(n);
|
||||
Self(ivalue)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&IValueImpl> for $native_type {
|
||||
type Error = WasmValueNativeCastError;
|
||||
|
||||
fn try_from(w: &IValue) -> Result<Self, Self::Error> {
|
||||
match w {
|
||||
IValue::$variant(n) => Ok(n.clone()),
|
||||
_ => Err(WasmValueNativeCastError {
|
||||
from: w.clone(),
|
||||
to: <$native_type>::INTERFACE_TYPE,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
native!(i8, S8);
|
||||
native!(i16, S16);
|
||||
native!(i32, I32);
|
||||
native!(i64, I64);
|
||||
native!(u8, U8);
|
||||
native!(u16, U16);
|
||||
native!(u32, U32);
|
||||
native!(u64, U64);
|
||||
native!(f32, F32);
|
||||
native!(f64, F64);
|
||||
native!(String, String);
|
||||
|
||||
/// Iterates over a vector of `IValues` but flatten all the
|
||||
/// values. So `I32(1), Record([I32(2), I32(3)]), I32(4)` will be
|
||||
/// iterated like `I32(1), I32(2), I32(3), I32(4)`.
|
||||
|
Loading…
Reference in New Issue
Block a user