decopule interface

This commit is contained in:
vms 2020-12-21 13:35:37 +03:00
parent 44d559cca1
commit 4b5da87cca
37 changed files with 521 additions and 522 deletions

18
Cargo.lock generated
View File

@ -18,6 +18,13 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "fluence-it-types"
version = "0.1.0"
dependencies = [
"serde",
]
[[package]]
name = "itoa"
version = "0.4.6"
@ -101,18 +108,18 @@ checksum = "50b8b2cd387f744f69469aaed197954ba4c0ecdb31e02edf99b023e0df11178a"
[[package]]
name = "serde"
version = "1.0.117"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.117"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
dependencies = [
"proc-macro2",
"quote",
@ -161,8 +168,9 @@ checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "wasmer-interface-types-fl"
version = "0.17.19"
version = "0.17.20"
dependencies = [
"fluence-it-types",
"log",
"nom",
"safe-transmute",

View File

@ -1,23 +1,13 @@
[package]
name = "wasmer-interface-types-fl"
version = "0.17.19"
description = "WebAssembly Interface Types library for Wasmer"
license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
repository = "https://github.com/wasmerio/wasmer"
edition = "2018"
[workspace]
members = [
"crates/it-types",
"wasmer-it",
]
[dependencies]
nom = "5.1"
wast = "8.0"
# `serde` is useful only to simplify the users' life. It is not
# required by WIT itself, is is used to cross the boundary between the
# host and WIT more easily, but it is not used inside Wasm.
serde = { version = "1.0", features = ["derive", "rc"], optional = true }
serde_json = "1.0"
safe-transmute = "0.11.0"
log = "0.4.11"
[features]
default = ["serde"]
[profile.release]
opt-level = 3
debug = false
lto = true
debug-assertions = false
overflow-checks = false
panic = "abort"

View File

@ -0,0 +1,9 @@
[package]
name = "fluence-it-types"
version = "0.1.0"
description = "Definitions of IValue and IType"
authors = ["Fluence Labs"]
edition = "2018"
[dependencies]
serde = { version = "1.0.118", features = ["derive", "rc"]}

View File

@ -0,0 +1,11 @@
mod types;
mod values;
pub mod vec1;
// types
pub use types::InterfaceType as IType;
pub use types::RecordFieldType as IRecordFieldType;
pub use types::RecordType as IRecordType;
// values
pub use values::InterfaceValue as IValue;

View File

@ -1,7 +1,9 @@
//! This module defines the WIT types.
use crate::vec1::Vec1;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use serde::Serialize;
/// Represents the types supported by WIT.
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]

View File

@ -0,0 +1,59 @@
//! Defines WIT values and associated operations.
use crate::vec1::Vec1;
/// A WIT value.
#[derive(Debug, Clone, PartialEq)]
pub enum InterfaceValue {
/// A 8-bits signed integer.
S8(i8),
/// A 16-bits signed integer.
S16(i16),
/// A 32-bits signed integer.
S32(i32),
/// A 64-bits signed integer.
S64(i64),
/// A 8-bits unsigned integer.
U8(u8),
/// A 16-bits unsigned integer.
U16(u16),
/// A 32-bits unsigned integer.
U32(u32),
/// A 64-bits unsigned integer.
U64(u64),
/// A 32-bits float.
F32(f32),
/// A 64-bits float.
F64(f64),
/// A string.
String(String),
/// A byte array.
Array(Vec<InterfaceValue>),
//Anyref(?),
/// A 32-bits integer (as defined in WebAssembly core).
I32(i32),
/// A 64-bits integer (as defiend in WebAssembly core).
I64(i64),
/// A record.
Record(Vec1<InterfaceValue>),
}
impl Default for InterfaceValue {
fn default() -> Self {
Self::I32(0)
}
}

View File

@ -1,218 +0,0 @@
//! Defines WIT values and associated operations.
use crate::{errors::WasmValueNativeCastError, types::InterfaceType, vec1::Vec1};
use std::{convert::TryFrom, slice::Iter};
#[cfg(feature = "serde")]
pub use crate::serde::{de::from_interface_values, ser::to_interface_value};
/// A WIT value.
#[derive(Debug, Clone, PartialEq)]
pub enum InterfaceValue {
/// A 8-bits signed integer.
S8(i8),
/// A 16-bits signed integer.
S16(i16),
/// A 32-bits signed integer.
S32(i32),
/// A 64-bits signed integer.
S64(i64),
/// A 8-bits unsigned integer.
U8(u8),
/// A 16-bits unsigned integer.
U16(u16),
/// A 32-bits unsigned integer.
U32(u32),
/// A 64-bits unsigned integer.
U64(u64),
/// A 32-bits float.
F32(f32),
/// A 64-bits float.
F64(f64),
/// A string.
String(String),
/// A byte array.
Array(Vec<InterfaceValue>),
//Anyref(?),
/// A 32-bits integer (as defined in WebAssembly core).
I32(i32),
/// A 64-bits integer (as defiend in WebAssembly core).
I64(i64),
/// A record.
Record(Vec1<InterfaceValue>),
}
impl Default for InterfaceValue {
fn default() -> Self {
Self::I32(0)
}
}
/// Represents a native type supported by WIT.
pub trait NativeType {
/// The associated interface type that maps to the native type.
const INTERFACE_TYPE: InterfaceType;
}
macro_rules! native {
($native_type:ty, $variant:ident) => {
impl NativeType for $native_type {
const INTERFACE_TYPE: InterfaceType = InterfaceType::$variant;
}
impl From<$native_type> for InterfaceValue {
fn from(n: $native_type) -> Self {
Self::$variant(n)
}
}
impl TryFrom<&InterfaceValue> for $native_type {
type Error = WasmValueNativeCastError;
fn try_from(w: &InterfaceValue) -> Result<Self, Self::Error> {
match w {
InterfaceValue::$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 `InterfaceValues` 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)`.
pub(crate) struct FlattenInterfaceValueIterator<'a> {
iterators: Vec<Iter<'a, InterfaceValue>>,
}
impl<'a> FlattenInterfaceValueIterator<'a> {
pub(crate) fn new(values: &'a [InterfaceValue]) -> Self {
Self {
iterators: vec![values.iter()],
}
}
}
impl<'a> Iterator for FlattenInterfaceValueIterator<'a> {
type Item = &'a InterfaceValue;
fn next(&mut self) -> Option<Self::Item> {
match self.iterators.last_mut()?.next() {
// End of the current iterator, go back to the previous
// one.
None => {
self.iterators.pop();
self.next()
}
// Recursively iterate over the record.
Some(InterfaceValue::Record(fields)) => {
self.iterators.push(fields.iter());
self.next()
}
// A regular item.
e @ Some(_) => e,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! value_to_type {
($test_name:ident, $ty:ident, $value:expr) => {
#[test]
#[allow(non_snake_case)]
fn $test_name() {
assert_eq!(
InterfaceType::from(&InterfaceValue::$ty($value)),
InterfaceType::$ty
);
}
};
}
value_to_type!(interface_type_from_interface_value__s8, S8, 42);
value_to_type!(interface_type_from_interface_value__s16, S16, 42);
value_to_type!(interface_type_from_interface_value__s32, S32, 42);
value_to_type!(interface_type_from_interface_value__s64, S64, 42);
value_to_type!(interface_type_from_interface_value__u8, U8, 42);
value_to_type!(interface_type_from_interface_value__u16, U16, 42);
value_to_type!(interface_type_from_interface_value__u32, U32, 42);
value_to_type!(interface_type_from_interface_value__u64, U64, 42);
value_to_type!(interface_type_from_interface_value__f32, F32, 42.);
value_to_type!(interface_type_from_interface_value__f64, F64, 42.);
value_to_type!(
interface_type_from_interface_value__string,
String,
"foo".to_string()
);
value_to_type!(interface_type_from_interface_value__i32, I32, 42);
value_to_type!(interface_type_from_interface_value__i64, I64, 42);
#[test]
#[allow(non_snake_case)]
fn interface_type_from_interface_value__record() {
assert_eq!(
InterfaceType::from(&InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::S8(2)
])),
InterfaceType::Record(RecordType {
fields: vec1![InterfaceType::I32, InterfaceType::S8]
})
);
assert_eq!(
InterfaceType::from(&InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::Record(vec1![
InterfaceValue::String("a".to_string()),
InterfaceValue::F64(42.)
]),
InterfaceValue::S8(2)
])),
InterfaceType::Record(RecordType {
fields: vec1![
InterfaceType::I32,
InterfaceType::Record(RecordType {
fields: vec1![InterfaceType::String, InterfaceType::F64]
}),
InterfaceType::S8
]
})
);
}
}

25
wasmer-it/Cargo.toml Normal file
View File

@ -0,0 +1,25 @@
[package]
name = "wasmer-interface-types-fl"
version = "0.17.20"
description = "WebAssembly Interface Types library for Wasmer"
license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
repository = "https://github.com/wasmerio/wasmer"
edition = "2018"
[dependencies]
fluence-it-types = { path = "../crates/it-types", version = "0.1.0" }
nom = "5.1"
wast = "8.0"
# `serde` is useful only to simplify the users' life. It is not
# required by WIT itself, is is used to cross the boundary between the
# host and WIT more easily, but it is not used inside Wasm.
serde = { version = "1.0", features = ["derive", "rc"], optional = true }
serde_json = "1.0"
safe-transmute = "0.11.0"
log = "0.4.11"
[features]
default = ["serde"]

View File

@ -3,7 +3,9 @@
use crate::{
interpreter::Instruction,
types::{InterfaceType, RecordType},
IValue,
IType,
IRecordType
};
use serde::Deserialize;
@ -28,7 +30,7 @@ pub struct FunctionArg {
pub name: String,
/// A function argument type.
pub ty: InterfaceType,
pub ty: IType,
}
/// Represents a type.
@ -44,7 +46,7 @@ pub enum Type {
arguments: Rc<Vec<FunctionArg>>,
/// Types for the results (`(result …)`).
output_types: Rc<Vec<InterfaceType>>,
output_types: Rc<Vec<IType>>,
},
/// A record type, like:
@ -52,7 +54,7 @@ pub enum Type {
/// ```wasm,ignore
/// (@interface type (record string i32))
/// ```
Record(Rc<RecordType>),
Record(Rc<IRecordType>),
}
/// Represents an imported function.
@ -100,7 +102,7 @@ pub struct Implementation {
/// Represents the kind of interface.
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
pub(crate) enum InterfaceKind {
pub enum InterfaceKind {
/// A type.
Type,

View File

@ -1,5 +1,8 @@
//! Parse the WIT binary representation into an [AST](crate::ast).
use crate::IType;
use crate::RecordFieldType;
use crate::RecordType;
use crate::{ast::*, interpreter::Instruction, types::*};
use nom::{
error::{make_error, ErrorKind, ParseError},
@ -100,7 +103,7 @@ fn function_arg<'input, E: ParseError<&'input [u8]>>(
/// Parse an interface type.
fn ty<'input, E: ParseError<&'input [u8]>>(
mut input: &'input [u8],
) -> IResult<&'input [u8], InterfaceType, E> {
) -> IResult<&'input [u8], IType, E> {
if input.is_empty() {
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
}
@ -108,29 +111,29 @@ fn ty<'input, E: ParseError<&'input [u8]>>(
consume!((input, opcode) = byte(input)?);
let ty = match opcode {
0x00 => InterfaceType::S8,
0x01 => InterfaceType::S16,
0x02 => InterfaceType::S32,
0x03 => InterfaceType::S64,
0x04 => InterfaceType::U8,
0x05 => InterfaceType::U16,
0x06 => InterfaceType::U32,
0x07 => InterfaceType::U64,
0x08 => InterfaceType::F32,
0x09 => InterfaceType::F64,
0x0a => InterfaceType::String,
0x00 => IType::S8,
0x01 => IType::S16,
0x02 => IType::S32,
0x03 => IType::S64,
0x04 => IType::U8,
0x05 => IType::U16,
0x06 => IType::U32,
0x07 => IType::U64,
0x08 => IType::F32,
0x09 => IType::F64,
0x0a => IType::String,
0x36 => {
consume!((input, array_value_type) = ty(input)?);
InterfaceType::Array(Box::new(array_value_type))
IType::Array(Box::new(array_value_type))
}
0x0b => InterfaceType::Anyref,
0x0c => InterfaceType::I32,
0x0d => InterfaceType::I64,
0x0b => IType::Anyref,
0x0c => IType::I32,
0x0d => IType::I64,
0x0e => {
consume!((input, record_id) = uleb(input)?);
InterfaceType::Record(record_id)
IType::Record(record_id)
}
_ => return Err(Err::Error(make_error(input, ErrorKind::ParseTo))),
};
@ -547,7 +550,7 @@ fn interfaces<'input, E: ParseError<&'input [u8]>>(
/// ast::{Adapter, Export, Implementation, Import, Interfaces, Type},
/// decoders::binary::parse,
/// interpreter::Instruction,
/// types::InterfaceType,
/// types::IType,
/// };
///
/// let input = &[
@ -588,8 +591,8 @@ fn interfaces<'input, E: ParseError<&'input [u8]>>(
/// &[] as &[u8],
/// 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",
@ -721,22 +724,22 @@ mod tests {
let output = Ok((
&[0x01][..],
vec![
InterfaceType::S8,
InterfaceType::S16,
InterfaceType::S32,
InterfaceType::S64,
InterfaceType::U8,
InterfaceType::U16,
InterfaceType::U32,
InterfaceType::U64,
InterfaceType::F32,
InterfaceType::F64,
InterfaceType::String,
InterfaceType::Anyref,
InterfaceType::I32,
InterfaceType::I64,
InterfaceType::Record(RecordType {
fields: vec1![InterfaceType::S32],
IType::S8,
IType::S16,
IType::S32,
IType::S64,
IType::U8,
IType::U16,
IType::U32,
IType::U64,
IType::F32,
IType::F64,
IType::String,
IType::Anyref,
IType::I32,
IType::I64,
IType::Record(RecordType {
fields: vec1![IType::S32],
}),
],
));
@ -766,18 +769,18 @@ mod tests {
&[0x01][..],
vec![
RecordType {
fields: vec1![InterfaceType::String],
fields: vec1![IType::String],
},
RecordType {
fields: vec1![InterfaceType::String, InterfaceType::I32],
fields: vec1![IType::String, IType::I32],
},
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,
],
},
],
@ -959,11 +962,11 @@ mod tests {
&[] as &[u8],
vec![
Type::Function {
inputs: vec![InterfaceType::S32, InterfaceType::S32],
outputs: vec![InterfaceType::S32],
inputs: vec![IType::S32, IType::S32],
outputs: vec![IType::S32],
},
Type::Record(RecordType {
fields: vec1![InterfaceType::S32, InterfaceType::S32],
fields: vec1![IType::S32, IType::S32],
}),
],
));
@ -1064,8 +1067,8 @@ mod tests {
&[] as &[u8],
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",

View File

@ -1,5 +1,11 @@
//! 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 std::rc::Rc;
pub use wast::parser::ParseBuffer as Buffer;
@ -83,82 +89,82 @@ mod keyword {
custom_keyword!(swap2 = "swap2");
}
impl Parse<'_> for InterfaceType {
fn parse(parser: Parser<'_>) -> Result<Self> {
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(InterfaceType::S8)
Ok(IType::S8)
} else if lookahead.peek::<keyword::s16>() {
parser.parse::<keyword::s16>()?;
Ok(InterfaceType::S16)
Ok(IType::S16)
} else if lookahead.peek::<keyword::s32>() {
parser.parse::<keyword::s32>()?;
Ok(InterfaceType::S32)
Ok(IType::S32)
} else if lookahead.peek::<keyword::s64>() {
parser.parse::<keyword::s64>()?;
Ok(InterfaceType::S64)
Ok(IType::S64)
} else if lookahead.peek::<keyword::u8>() {
parser.parse::<keyword::u8>()?;
Ok(InterfaceType::U8)
Ok(IType::U8)
} else if lookahead.peek::<keyword::u16>() {
parser.parse::<keyword::u16>()?;
Ok(InterfaceType::U16)
Ok(IType::U16)
} else if lookahead.peek::<keyword::u32>() {
parser.parse::<keyword::u32>()?;
Ok(InterfaceType::U32)
Ok(IType::U32)
} else if lookahead.peek::<keyword::u64>() {
parser.parse::<keyword::u64>()?;
Ok(InterfaceType::U64)
Ok(IType::U64)
} else if lookahead.peek::<keyword::f32>() {
parser.parse::<keyword::f32>()?;
Ok(InterfaceType::F32)
Ok(IType::F32)
} else if lookahead.peek::<keyword::f64>() {
parser.parse::<keyword::f64>()?;
Ok(InterfaceType::F64)
Ok(IType::F64)
} else if lookahead.peek::<keyword::string>() {
parser.parse::<keyword::string>()?;
Ok(InterfaceType::String)
Ok(IType::String)
} else if lookahead.peek::<keyword::array>() {
parser.parse::<keyword::array>()?;
let array_type = parser.parens(|p| p.parse())?;
Ok(InterfaceType::Array(Box::new(array_type)))
Ok(IType::Array(Box::new(array_type)))
} else if lookahead.peek::<keyword::anyref>() {
parser.parse::<keyword::anyref>()?;
Ok(InterfaceType::Anyref)
Ok(IType::Anyref)
} else if lookahead.peek::<keyword::i32>() {
parser.parse::<keyword::i32>()?;
Ok(InterfaceType::I32)
Ok(IType::I32)
} else if lookahead.peek::<keyword::i64>() {
parser.parse::<keyword::i64>()?;
Ok(InterfaceType::I64)
Ok(IType::I64)
} else if lookahead.peek::<keyword::record>() {
parser.parse::<keyword::record>()?;
Ok(InterfaceType::Record(parser.parse()?))
Ok(IType::Record(parser.parse()?))
} else {
Err(lookahead.error())
}
}
}
impl Parse<'_> for RecordType {
impl Parse<'_> for RecordTypeImpl {
fn parse(parser: Parser<'_>) -> Result<Self> {
parser.parse::<keyword::record>()?;
@ -194,19 +200,24 @@ impl Parse<'_> for RecordType {
}
let ty = parser.parse()?;
fields.push(RecordFieldType {
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(())
})?;
Ok(RecordType {
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)
}
}
@ -449,7 +460,7 @@ impl Parse<'_> for AtInterface {
#[derive(PartialEq, Debug)]
enum FunctionType {
Header(Vec<FunctionArg>),
Output(Vec<InterfaceType>),
Output(Vec<IType>),
}
impl Parse<'_> for FunctionType {
@ -478,7 +489,7 @@ impl Parse<'_> for FunctionType {
})?;
}
let arg_type: InterfaceType = parser.parse()?;
let arg_type: IType = parser.parse()?;
arguments.push(FunctionArg {
name: arg_name.trim_end_matches(':').to_string(),
@ -705,7 +716,7 @@ impl<'a> Parse<'a> for Interfaces<'a> {
/// ast::{Adapter, Export, Implementation, Import, Interfaces, Type},
/// decoders::wat::{parse, Buffer},
/// interpreter::Instruction,
/// types::InterfaceType,
/// types::IType,
/// };
///
/// let input = Buffer::new(
@ -722,8 +733,8 @@ impl<'a> Parse<'a> for Interfaces<'a> {
/// .unwrap();
/// let output = 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",
@ -779,32 +790,29 @@ mod tests {
"record (field string)",
];
let outputs = vec![
InterfaceType::S8,
InterfaceType::S16,
InterfaceType::S32,
InterfaceType::S64,
InterfaceType::U8,
InterfaceType::U16,
InterfaceType::U32,
InterfaceType::U64,
InterfaceType::F32,
InterfaceType::F64,
InterfaceType::String,
InterfaceType::Anyref,
InterfaceType::I32,
InterfaceType::I64,
InterfaceType::Record(RecordType {
fields: vec1![InterfaceType::String],
IType::S8,
IType::S16,
IType::S32,
IType::S64,
IType::U8,
IType::U16,
IType::U32,
IType::U64,
IType::F32,
IType::F64,
IType::String,
IType::Anyref,
IType::I32,
IType::I64,
IType::Record(RecordType {
fields: vec1![IType::String],
}),
];
assert_eq!(inputs.len(), outputs.len());
for (input, output) in inputs.iter().zip(outputs.iter()) {
assert_eq!(
&parser::parse::<InterfaceType>(&buffer(input)).unwrap(),
output
);
assert_eq!(&parser::parse::<IType>(&buffer(input)).unwrap(), output);
}
}
@ -817,18 +825,18 @@ mod tests {
];
let outputs = vec![
RecordType {
fields: vec1![InterfaceType::String],
fields: vec1![IType::String],
},
RecordType {
fields: vec1![InterfaceType::String, InterfaceType::I32],
fields: vec1![IType::String, IType::I32],
},
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,
],
},
];
@ -951,7 +959,7 @@ mod tests {
#[test]
fn test_param() {
let input = buffer("(param i32 string)");
let output = FunctionType::InputTypes(vec![InterfaceType::I32, InterfaceType::String]);
let output = FunctionType::InputTypes(vec![IType::I32, IType::String]);
assert_eq!(parser::parse::<FunctionType>(&input).unwrap(), output);
}
@ -967,7 +975,7 @@ mod tests {
#[test]
fn test_result() {
let input = buffer("(result i32 string)");
let output = FunctionType::Output(vec![InterfaceType::I32, InterfaceType::String]);
let output = FunctionType::Output(vec![IType::I32, IType::String]);
assert_eq!(parser::parse::<FunctionType>(&input).unwrap(), output);
}
@ -976,8 +984,8 @@ mod tests {
fn test_type_function() {
let input = buffer(r#"(@interface type (func (param i32 i32) (result i32)))"#);
let output = Interface::Type(Type::Function {
inputs: vec![InterfaceType::I32, InterfaceType::I32],
outputs: vec![InterfaceType::I32],
inputs: vec![IType::I32, IType::I32],
outputs: vec![IType::I32],
});
assert_eq!(parser::parse::<Interface>(&input).unwrap(), output);
@ -987,7 +995,7 @@ mod tests {
fn test_type_record() {
let input = buffer(r#"(@interface type (record (field string) (field i32)))"#);
let output = Interface::Type(Type::Record(RecordType {
fields: vec1![InterfaceType::String, InterfaceType::I32],
fields: vec1![IType::String, IType::I32],
}));
assert_eq!(parser::parse::<Interface>(&input).unwrap(), output);
@ -1064,8 +1072,8 @@ mod tests {
);
let output = 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",

View File

@ -3,6 +3,11 @@
use crate::{ast::*, interpreter::Instruction, types::*};
use std::io::{self, Write};
use crate::IType;
use crate::ITypeImpl;
use crate::RecordFieldTypeImpl;
use crate::RecordTypeImpl;
/// A trait for converting a value to bytes.
pub trait ToBytes<W>
where
@ -106,31 +111,31 @@ where
}
/// Encode an `InterfaceType` into bytes.
impl<W> ToBytes<W> for InterfaceType
impl<W> ToBytes<W> for ITypeImpl
where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
match self {
InterfaceType::S8 => 0x00_u8.to_bytes(writer),
InterfaceType::S16 => 0x01_u8.to_bytes(writer),
InterfaceType::S32 => 0x02_u8.to_bytes(writer),
InterfaceType::S64 => 0x03_u8.to_bytes(writer),
InterfaceType::U8 => 0x04_u8.to_bytes(writer),
InterfaceType::U16 => 0x05_u8.to_bytes(writer),
InterfaceType::U32 => 0x06_u8.to_bytes(writer),
InterfaceType::U64 => 0x07_u8.to_bytes(writer),
InterfaceType::F32 => 0x08_u8.to_bytes(writer),
InterfaceType::F64 => 0x09_u8.to_bytes(writer),
InterfaceType::String => 0x0a_u8.to_bytes(writer),
InterfaceType::Array(ty) => {
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)
}
InterfaceType::Anyref => 0x0b_u8.to_bytes(writer),
InterfaceType::I32 => 0x0c_u8.to_bytes(writer),
InterfaceType::I64 => 0x0d_u8.to_bytes(writer),
InterfaceType::Record(record_id) => {
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)
}
@ -139,24 +144,26 @@ where
}
/// Encode a `RecordType` into bytes.
impl<W> ToBytes<W> for RecordFieldType
impl<W> ToBytes<W> for RecordFieldTypeImpl
where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.name.as_str().to_bytes(writer)?;
self.ty.to_bytes(writer)
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 RecordType
impl<W> ToBytes<W> for RecordTypeImpl
where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.name.as_str().to_bytes(writer)?;
self.fields.to_bytes(writer)
let record_type = &self.0;
record_type.name.as_str().to_bytes(writer)?;
record_type.fields.to_bytes(writer)
}
}

View File

@ -55,50 +55,55 @@
//! assert_eq!(input, output);
//! ```
use crate::IType;
use crate::ITypeImpl;
use crate::RecordTypeImpl;
use crate::{ast::*, interpreter::Instruction, types::*};
use std::string::ToString;
/// Encode an `InterfaceType` into a string.
impl ToString for &InterfaceType {
impl ToString for &ITypeImpl {
fn to_string(&self) -> String {
match self {
InterfaceType::S8 => "s8".to_string(),
InterfaceType::S16 => "s16".to_string(),
InterfaceType::S32 => "s32".to_string(),
InterfaceType::S64 => "s64".to_string(),
InterfaceType::U8 => "u8".to_string(),
InterfaceType::U16 => "u16".to_string(),
InterfaceType::U32 => "u32".to_string(),
InterfaceType::U64 => "u64".to_string(),
InterfaceType::F32 => "f32".to_string(),
InterfaceType::F64 => "f64".to_string(),
InterfaceType::String => "string".to_string(),
InterfaceType::Array(ty) => format!("array ({})", ty.as_ref().to_string()),
InterfaceType::Anyref => "anyref".to_string(),
InterfaceType::I32 => "i32".to_string(),
InterfaceType::I64 => "i64".to_string(),
InterfaceType::Record(record_type_id) => format!("record {}", record_type_id),
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 &RecordType {
impl ToString for &RecordTypeImpl {
fn to_string(&self) -> String {
let record_type = &self.0;
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
}),
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
}),
)
}
}
@ -192,7 +197,7 @@ fn encode_function_arguments(arguments: &[FunctionArg]) -> String {
/// Encode a list of `InterfaceType` representing outputs into a
/// string.
fn output_types_to_result(output_types: &[InterfaceType]) -> String {
fn output_types_to_result(output_types: &[IType]) -> String {
if output_types.is_empty() {
"".into()
} else {

View File

@ -455,7 +455,7 @@ where
Some(InterfaceValue::Record(record_values))
if record_type == &(&*record_values).into() =>
{
let values = FlattenInterfaceValueIterator::new(&record_values);
let values = FlattenIValueIterator::new(&record_values);
for value in values {
runtime.stack.push(value.clone());
}

View File

@ -53,8 +53,7 @@
#![doc(html_favicon_url = "https://wasmer.io/static/icons/favicon.ico")]
#![doc(html_logo_url = "https://github.com/wasmerio.png")]
pub mod ast;
pub mod types;
mod ast;
#[macro_use]
mod macros;
pub mod decoders;
@ -63,5 +62,15 @@ pub mod errors;
pub mod interpreter;
#[cfg(feature = "serde")]
mod serde;
pub mod values;
pub mod vec1;
mod values;
pub use fluence_it_types::vec1::Vec1;
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);

View File

@ -1,16 +1,13 @@
//! Provides a deserializer from WIT values to Rust value.
use crate::{
types::InterfaceType,
values::{FlattenInterfaceValueIterator, InterfaceValue},
};
use crate::{values::FlattenIValueIterator, IType, IValue};
use serde::{de, Deserialize};
use std::{
fmt::{self, Display},
iter::Peekable,
};
/// Deserialize a set of `InterfaceValue`s to a type `T` that
/// Deserialize a set of `IValue`s to a type `T` that
/// implements the `Deserialize` trait.
///
/// This is not a requirement to use WIT, but Serde provides an even
@ -21,7 +18,7 @@ use std::{
///
/// ```rust
/// use wasmer_interface_types::{
/// values::{InterfaceValue, from_interface_values},
/// values::{IValue, from_interface_values},
/// vec1::Vec1,
/// };
/// use serde::Deserialize;
@ -36,10 +33,10 @@ use std::{
/// y: f32,
/// };
///
/// let values = vec![InterfaceValue::Record(Vec1::new(vec![
/// InterfaceValue::String("abc".to_string()),
/// InterfaceValue::Record(Vec1::new(vec![InterfaceValue::I32(1), InterfaceValue::I64(2)]).unwrap()),
/// InterfaceValue::F32(3.),
/// let values = vec![IValue::Record(Vec1::new(vec![
/// IValue::String("abc".to_string()),
/// IValue::Record(Vec1::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()),
/// IValue::F32(3.),
/// ]).unwrap())];
/// let t = from_interface_values::<T>(&values).unwrap();
///
@ -52,7 +49,7 @@ use std::{
/// }
/// );
/// ```
pub fn from_interface_values<'a, T>(values: &'a [InterfaceValue]) -> Result<T, DeserializeError>
pub fn from_interface_values<'a, T>(values: &'a [IValue]) -> Result<T, DeserializeError>
where
T: Deserialize<'a>,
{
@ -66,15 +63,15 @@ where
}
/// The deserializer. The iterator iterates over `InterfaceValue`s,
/// all flatten, see `FlattenInterfaceValueIterator`.
/// all flatten, see `FlattenIValueIterator`.
struct Deserializer<'de> {
iterator: Peekable<FlattenInterfaceValueIterator<'de>>,
iterator: Peekable<FlattenIValueIterator<'de>>,
}
impl<'de> Deserializer<'de> {
pub fn new(input: &'de [InterfaceValue]) -> Deserializer<'de> {
Deserializer {
iterator: FlattenInterfaceValueIterator::new(input).peekable(),
iterator: FlattenIValueIterator::new(input).peekable(),
}
}
}
@ -83,14 +80,14 @@ macro_rules! next {
($method_name:ident, $variant:ident, $type:ty) => {
fn $method_name(&mut self) -> Result<$type, DeserializeError> {
match self.iterator.peek() {
Some(InterfaceValue::$variant(value)) => {
Some(IValue::$variant(value)) => {
self.iterator.next();
Ok(*value)
}
Some(wrong_value) => Err(DeserializeError::TypeMismatch {
expected_type: InterfaceType::$variant,
expected_type: IType::$variant,
received_value: (*wrong_value).clone(),
}),
@ -114,14 +111,14 @@ impl<'de> Deserializer<'de> {
fn next_string(&mut self) -> Result<&'de str, DeserializeError> {
match self.iterator.peek() {
Some(InterfaceValue::String(v)) => {
Some(IValue::String(v)) => {
self.iterator.next();
Ok(v)
}
Some(wrong_value) => Err(DeserializeError::TypeMismatch {
expected_type: InterfaceType::String,
expected_type: IType::String,
received_value: (*wrong_value).clone(),
}),
@ -131,7 +128,7 @@ impl<'de> Deserializer<'de> {
fn next_array(&mut self) -> Result<&'de [u8], DeserializeError> {
match self.iterator.peek() {
Some(InterfaceValue::Array(_)) => {
Some(IValue::Array(_)) => {
self.iterator.next();
// Ok(v)
@ -141,7 +138,7 @@ impl<'de> Deserializer<'de> {
Some(wrong_value) => Err(DeserializeError::TypeMismatch {
// TODO: change default
expected_type: InterfaceType::Array(Box::new(InterfaceType::S8)),
expected_type: IType::Array(Box::new(IType::S8)),
received_value: (*wrong_value).clone(),
}),
@ -165,10 +162,10 @@ pub enum DeserializeError {
/// The current value hasn't the expected type.
TypeMismatch {
/// The expected type.
expected_type: InterfaceType,
expected_type: IType,
/// The received type.
received_value: InterfaceValue,
received_value: IValue,
},
/// Arbitrary message.
@ -209,21 +206,21 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: de::Visitor<'de>,
{
match self.iterator.peek() {
Some(InterfaceValue::S8(_)) => self.deserialize_i8(visitor),
Some(InterfaceValue::S16(_)) => self.deserialize_i16(visitor),
Some(InterfaceValue::S32(_)) => self.deserialize_i32(visitor),
Some(InterfaceValue::S64(_)) => self.deserialize_i64(visitor),
Some(InterfaceValue::U8(_)) => self.deserialize_u8(visitor),
Some(InterfaceValue::U16(_)) => self.deserialize_u16(visitor),
Some(InterfaceValue::U32(_)) => self.deserialize_u32(visitor),
Some(InterfaceValue::U64(_)) => self.deserialize_u64(visitor),
Some(InterfaceValue::F32(_)) => self.deserialize_f32(visitor),
Some(InterfaceValue::F64(_)) => self.deserialize_f64(visitor),
Some(InterfaceValue::String(_)) => self.deserialize_string(visitor),
Some(InterfaceValue::Array(_)) => self.deserialize_bytes(visitor),
Some(InterfaceValue::I32(_)) => self.deserialize_i32(visitor),
Some(InterfaceValue::I64(_)) => self.deserialize_i64(visitor),
Some(InterfaceValue::Record(..)) => unreachable!("Records should have been flattened."), // already flattened
Some(IValue::S8(_)) => self.deserialize_i8(visitor),
Some(IValue::S16(_)) => self.deserialize_i16(visitor),
Some(IValue::S32(_)) => self.deserialize_i32(visitor),
Some(IValue::S64(_)) => self.deserialize_i64(visitor),
Some(IValue::U8(_)) => self.deserialize_u8(visitor),
Some(IValue::U16(_)) => self.deserialize_u16(visitor),
Some(IValue::U32(_)) => self.deserialize_u32(visitor),
Some(IValue::U64(_)) => self.deserialize_u64(visitor),
Some(IValue::F32(_)) => self.deserialize_f32(visitor),
Some(IValue::F64(_)) => self.deserialize_f64(visitor),
Some(IValue::String(_)) => self.deserialize_string(visitor),
Some(IValue::Array(_)) => self.deserialize_bytes(visitor),
Some(IValue::I32(_)) => self.deserialize_i32(visitor),
Some(IValue::I64(_)) => self.deserialize_i64(visitor),
Some(IValue::Record(..)) => unreachable!("Records should have been flattened."), // already flattened
None => Err(DeserializeError::InputEmpty),
}
}
@ -253,7 +250,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: de::Visitor<'de>,
{
// Both `InterfaceValue::S32` and `InterfaceValue::I32`
// Both `IValue::S32` and `IValue::I32`
// represent `i32`.
visitor.visit_i32(self.next_s32().or_else(|_| self.next_i32())?)
}
@ -262,7 +259,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: de::Visitor<'de>,
{
// Both `InterfaceValue::S64` and `InterfaceValue::I64`
// Both `IValue::S64` and `IValue::I64`
// represent `i64`.
visitor.visit_i64(self.next_s64().or_else(|_| self.next_i64())?)
}
@ -489,7 +486,7 @@ mod tests {
#[test]
#[allow(non_snake_case)]
fn $test_name() {
let input = vec![InterfaceValue::$variant($value)];
let input = vec![IValue::$variant($value)];
let output: $ty = $value;
assert_eq!(from_interface_values::<$ty>(&input).unwrap(), output);
@ -518,7 +515,7 @@ mod tests {
#[allow(non_snake_case)]
fn test_deserialize_value__str() {
let foo = "foo".to_string();
let values = vec![InterfaceValue::String(foo)];
let values = vec![IValue::String(foo)];
let input: &str = from_interface_values(&values).unwrap();
let output: &str = "foo";
@ -534,7 +531,7 @@ mod tests {
#[derive(Deserialize, Debug, PartialEq)]
struct S(i8);
let input = vec![InterfaceValue::Record(vec1![InterfaceValue::S8(42)])];
let input = vec![IValue::Record(vec1![IValue::S8(42)])];
let output = S(42);
assert_eq!(from_interface_values::<S>(&input).unwrap(), output);
@ -546,10 +543,7 @@ mod tests {
#[derive(Deserialize, Debug, PartialEq)]
struct S(i8, f32);
let input = vec![InterfaceValue::Record(vec1![
InterfaceValue::S8(7),
InterfaceValue::F32(42.),
])];
let input = vec![IValue::Record(vec1![IValue::S8(7), IValue::F32(42.),])];
let output = S(7, 42.);
assert_eq!(from_interface_values::<S>(&input).unwrap(), output);
@ -564,10 +558,7 @@ mod tests {
y: f32,
}
let input = vec![InterfaceValue::Record(vec1![
InterfaceValue::S8(7),
InterfaceValue::F32(42.),
])];
let input = vec![IValue::Record(vec1![IValue::S8(7), IValue::F32(42.),])];
let output = S { x: 7, y: 42. };
assert_eq!(from_interface_values::<S>(&input).unwrap(), output);
@ -589,17 +580,9 @@ mod tests {
p2: Point,
}
let input = vec![InterfaceValue::Record(vec1![
InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::I32(2),
InterfaceValue::I32(3),
]),
InterfaceValue::Record(vec1![
InterfaceValue::I32(4),
InterfaceValue::I32(5),
InterfaceValue::I32(6),
]),
let input = vec![IValue::Record(vec1![
IValue::Record(vec1![IValue::I32(1), IValue::I32(2), IValue::I32(3),]),
IValue::Record(vec1![IValue::I32(4), IValue::I32(5), IValue::I32(6),]),
])];
let output = Line {
p1: Point { x: 1, y: 2, z: 3 },

View File

@ -1,11 +1,13 @@
//! Provides a serializer from Rust value to WIT values.
use crate::{values::InterfaceValue, vec1::Vec1};
use crate::IValue;
use crate::IValueImpl;
use crate::Vec1;
use serde::{ser, Serialize};
use std::fmt::{self, Display};
/// Serialize a type `T` that implements the `Serialize` trait to an
/// `InterfaceValue`.
/// `IValue`.
///
/// This is not a requirement to use WIT, but Serde provides an even
/// nicer API to the user to send its complex types to WIT.
@ -14,7 +16,7 @@ use std::fmt::{self, Display};
///
/// ```rust
/// use wasmer_interface_types::{
/// values::{InterfaceValue, to_interface_value},
/// values::{IValue, to_interface_value},
/// vec1::Vec1,
/// };
/// use serde::Serialize;
@ -37,18 +39,19 @@ use std::fmt::{self, Display};
///
/// assert_eq!(
/// to_interface_value(&input).unwrap(),
/// InterfaceValue::Record(Vec1::new(vec![
/// InterfaceValue::String("abc".to_string()),
/// InterfaceValue::Record(Vec1::new(vec![InterfaceValue::I32(1), InterfaceValue::I64(2)]).unwrap()),
/// InterfaceValue::F32(3.),
/// IValue::Record(Vec1::new(vec![
/// IValue::String("abc".to_string()),
/// IValue::Record(Vec1::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()),
/// IValue::F32(3.),
/// ]).unwrap()),
/// );
/// ```
pub fn to_interface_value<T>(value: &T) -> Result<InterfaceValue, SerializeError>
pub fn to_interface_value<T>(value: &T) -> Result<IValue, SerializeError>
where
T: Serialize,
{
let mut serializer = Serializer::new();
let value = ValueImpl(value);
value.serialize(&mut serializer)?;
if serializer.values.len() != 1 {
@ -61,14 +64,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)
Ok(first_value.0)
}
}
}
/// The serializer.
struct Serializer {
values: Vec<Vec<InterfaceValue>>,
values: Vec<Vec<IValueImpl>>,
}
impl Serializer {
@ -78,7 +81,7 @@ impl Serializer {
}
}
fn last(&mut self) -> &mut Vec<InterfaceValue> {
fn last(&mut self) -> &mut Vec<IValueImpl> {
self.values.last_mut().unwrap()
}
@ -86,7 +89,7 @@ impl Serializer {
self.values.push(Vec::with_capacity(capacity));
}
fn pop(&mut self) -> Result<Vec<InterfaceValue>, SerializeError> {
fn pop(&mut self) -> Result<Vec<IValueImpl>, SerializeError> {
// The first `vec` contains the final result. It is forbidden
// to `pop` it as is.
if self.values.len() < 2 {
@ -361,9 +364,10 @@ impl<'a> ser::SerializeSeq for &'a mut Serializer {
}
fn end(self) -> Result<Self::Ok, Self::Error> {
let record = InterfaceValue::Record(
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
);
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
let record = IValue::Array(values);
let record = IValueImpl(record);
self.last().push(record);
Ok(())
@ -398,9 +402,11 @@ impl<'a> ser::SerializeTupleStruct for &'a mut Serializer {
}
fn end(self) -> Result<Self::Ok, Self::Error> {
let record = InterfaceValue::Record(
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
);
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);
self.last().push(record);
Ok(())
@ -442,9 +448,11 @@ impl<'a> ser::SerializeMap for &'a mut Serializer {
}
fn end(self) -> Result<Self::Ok, Self::Error> {
let record = InterfaceValue::Record(
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
);
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);
self.last().push(record);
Ok(())
@ -463,9 +471,11 @@ impl<'a> ser::SerializeStruct for &'a mut Serializer {
}
fn end(self) -> Result<Self::Ok, Self::Error> {
let record = InterfaceValue::Record(
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
);
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);
self.last().push(record);
Ok(())
@ -502,7 +512,7 @@ mod tests {
#[allow(non_snake_case)]
fn $test_name() {
let input: $ty = $value;
let output = InterfaceValue::$variant($value);
let output = IValue::$variant($value);
assert_eq!(to_interface_value(&input).unwrap(), output);
}
@ -533,7 +543,7 @@ mod tests {
struct S(i8);
let input = S(42);
let output = InterfaceValue::S8(42);
let output = IValue::S8(42);
assert_eq!(to_interface_value(&input).unwrap(), output);
}
@ -545,7 +555,7 @@ mod tests {
struct S(i8, f32);
let input = S(7, 42.);
let output = InterfaceValue::Record(vec1![InterfaceValue::S8(7), InterfaceValue::F32(42.)]);
let output = IValue::Record(vec1![IValue::S8(7), IValue::F32(42.)]);
assert_eq!(to_interface_value(&input).unwrap(), output);
}
@ -560,7 +570,7 @@ mod tests {
}
let input = S { x: 7, y: 42. };
let output = InterfaceValue::Record(vec1![InterfaceValue::S8(7), InterfaceValue::F32(42.)]);
let output = IValue::Record(vec1![IValue::S8(7), IValue::F32(42.)]);
assert_eq!(to_interface_value(&input).unwrap(), output);
}
@ -585,17 +595,9 @@ mod tests {
p1: Point { x: 1, y: 2, z: 3 },
p2: Point { x: 4, y: 5, z: 6 },
};
let output = InterfaceValue::Record(vec1![
InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::I32(2),
InterfaceValue::I32(3),
]),
InterfaceValue::Record(vec1![
InterfaceValue::I32(4),
InterfaceValue::I32(5),
InterfaceValue::I32(6),
]),
let output = IValue::Record(vec1![
IValue::Record(vec1![IValue::I32(1), IValue::I32(2), IValue::I32(3),]),
IValue::Record(vec1![IValue::I32(4), IValue::I32(5), IValue::I32(6),]),
]);
assert_eq!(to_interface_value(&input).unwrap(), output);

94
wasmer-it/src/values.rs Normal file
View File

@ -0,0 +1,94 @@
use crate::IType;
use crate::IValue;
use crate::IValueImpl;
use crate::{errors::WasmValueNativeCastError, types::IType, vec1::Vec1};
use std::{convert::TryFrom, 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)`.
pub(crate) struct FlattenIValueIterator<'a> {
iterators: Vec<Iter<'a, IValue>>,
}
impl<'a> FlattenIValueIterator<'a> {
pub(crate) fn new(values: &'a [IValue]) -> Self {
Self {
iterators: vec![values.iter()],
}
}
}
impl<'a> Iterator for FlattenIValueIterator<'a> {
type Item = &'a IValue;
fn next(&mut self) -> Option<Self::Item> {
match self.iterators.last_mut()?.next() {
// End of the current iterator, go back to the previous
// one.
None => {
self.iterators.pop();
self.next()
}
// Recursively iterate over the record.
Some(IValue::Record(fields)) => {
self.iterators.push(fields.iter());
self.next()
}
// A regular item.
e @ Some(_) => e,
}
}
}