From 44d559cca195a2c403d771ba039903b326cf31d9 Mon Sep 17 00:00:00 2001 From: vms Date: Tue, 10 Nov 2020 20:17:49 +0300 Subject: [PATCH 1/7] use log::debug in call-core --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/interpreter/instructions/call_core.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97921f4..1af01fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,7 +161,7 @@ checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "wasmer-interface-types-fl" -version = "0.17.18" +version = "0.17.19" dependencies = [ "log", "nom", diff --git a/Cargo.toml b/Cargo.toml index 9d758a0..e4e2df5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-interface-types-fl" -version = "0.17.18" +version = "0.17.19" description = "WebAssembly Interface Types library for Wasmer" license = "MIT" authors = ["The Wasmer Engineering Team "] diff --git a/src/interpreter/instructions/call_core.rs b/src/interpreter/instructions/call_core.rs index 73e7c59..1785a7e 100644 --- a/src/interpreter/instructions/call_core.rs +++ b/src/interpreter/instructions/call_core.rs @@ -31,7 +31,7 @@ executable_instruction!( super::check_function_signature(&**instance, local_or_import, &inputs, instruction.clone())?; - log::info!("call-core: calling {} with arguments: {:?}", local_or_import.name(), inputs); + log::debug!("call-core: calling {} with arguments: {:?}", local_or_import.name(), inputs); let outputs = local_or_import.call(&inputs).map_err(|_| { InstructionError::new( @@ -42,7 +42,7 @@ executable_instruction!( ) })?; - log::info!("call-core: call to {} succeeded with result {:?}", local_or_import.name(), outputs); + log::debug!("call-core: call to {} succeeded with result {:?}", local_or_import.name(), outputs); for output in outputs.into_iter() { runtime.stack.push(output) From 4b5da87cca5663d47d35b694ca3b3ace70310d32 Mon Sep 17 00:00:00 2001 From: vms Date: Mon, 21 Dec 2020 13:35:37 +0300 Subject: [PATCH 2/7] decopule interface --- Cargo.lock | 18 +- Cargo.toml | 34 +-- crates/it-types/Cargo.toml | 9 + crates/it-types/src/lib.rs | 11 + {src => crates/it-types/src}/types.rs | 4 +- crates/it-types/src/values.rs | 59 +++++ {src => crates/it-types/src}/vec1.rs | 0 src/values.rs | 218 ------------------ wasmer-it/Cargo.toml | 25 ++ {src => wasmer-it/src}/ast.rs | 12 +- {src => wasmer-it/src}/decoders/binary.rs | 97 ++++---- {src => wasmer-it/src}/decoders/mod.rs | 0 {src => wasmer-it/src}/decoders/wat.rs | 132 ++++++----- {src => wasmer-it/src}/encoders/binary.rs | 55 +++-- {src => wasmer-it/src}/encoders/mod.rs | 0 {src => wasmer-it/src}/encoders/wat.rs | 71 +++--- {src => wasmer-it/src}/errors.rs | 0 .../interpreter/instructions/argument_get.rs | 0 .../src}/interpreter/instructions/arrays.rs | 0 .../interpreter/instructions/call_core.rs | 0 .../src}/interpreter/instructions/dup.rs | 0 .../src}/interpreter/instructions/mod.rs | 0 .../src}/interpreter/instructions/numbers.rs | 0 .../src}/interpreter/instructions/records.rs | 2 +- .../src}/interpreter/instructions/strings.rs | 0 .../src}/interpreter/instructions/swap2.rs | 0 .../src}/interpreter/instructions/utils.rs | 0 {src => wasmer-it/src}/interpreter/mod.rs | 0 {src => wasmer-it/src}/interpreter/stack.rs | 0 .../src}/interpreter/wasm/mod.rs | 0 .../src}/interpreter/wasm/structures.rs | 0 {src => wasmer-it/src}/lib.rs | 17 +- {src => wasmer-it/src}/macros.rs | 0 {src => wasmer-it/src}/serde/de.rs | 105 ++++----- {src => wasmer-it/src}/serde/mod.rs | 0 {src => wasmer-it/src}/serde/ser.rs | 80 +++---- wasmer-it/src/values.rs | 94 ++++++++ 37 files changed, 521 insertions(+), 522 deletions(-) create mode 100644 crates/it-types/Cargo.toml create mode 100644 crates/it-types/src/lib.rs rename {src => crates/it-types/src}/types.rs (97%) create mode 100644 crates/it-types/src/values.rs rename {src => crates/it-types/src}/vec1.rs (100%) delete mode 100644 src/values.rs create mode 100644 wasmer-it/Cargo.toml rename {src => wasmer-it/src}/ast.rs (94%) rename {src => wasmer-it/src}/decoders/binary.rs (93%) rename {src => wasmer-it/src}/decoders/mod.rs (100%) rename {src => wasmer-it/src}/decoders/wat.rs (92%) rename {src => wasmer-it/src}/encoders/binary.rs (94%) rename {src => wasmer-it/src}/encoders/mod.rs (100%) rename {src => wasmer-it/src}/encoders/wat.rs (92%) rename {src => wasmer-it/src}/errors.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/argument_get.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/arrays.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/call_core.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/dup.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/mod.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/numbers.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/records.rs (99%) rename {src => wasmer-it/src}/interpreter/instructions/strings.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/swap2.rs (100%) rename {src => wasmer-it/src}/interpreter/instructions/utils.rs (100%) rename {src => wasmer-it/src}/interpreter/mod.rs (100%) rename {src => wasmer-it/src}/interpreter/stack.rs (100%) rename {src => wasmer-it/src}/interpreter/wasm/mod.rs (100%) rename {src => wasmer-it/src}/interpreter/wasm/structures.rs (100%) rename {src => wasmer-it/src}/lib.rs (85%) rename {src => wasmer-it/src}/macros.rs (100%) rename {src => wasmer-it/src}/serde/de.rs (80%) rename {src => wasmer-it/src}/serde/mod.rs (100%) rename {src => wasmer-it/src}/serde/ser.rs (87%) create mode 100644 wasmer-it/src/values.rs diff --git a/Cargo.lock b/Cargo.lock index 1af01fa..481211e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index e4e2df5..196e565 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 "] -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" diff --git a/crates/it-types/Cargo.toml b/crates/it-types/Cargo.toml new file mode 100644 index 0000000..ca30c9f --- /dev/null +++ b/crates/it-types/Cargo.toml @@ -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"]} diff --git a/crates/it-types/src/lib.rs b/crates/it-types/src/lib.rs new file mode 100644 index 0000000..893c264 --- /dev/null +++ b/crates/it-types/src/lib.rs @@ -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; diff --git a/src/types.rs b/crates/it-types/src/types.rs similarity index 97% rename from src/types.rs rename to crates/it-types/src/types.rs index 95bb2da..3310ebe 100644 --- a/src/types.rs +++ b/crates/it-types/src/types.rs @@ -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)] diff --git a/crates/it-types/src/values.rs b/crates/it-types/src/values.rs new file mode 100644 index 0000000..7b765f4 --- /dev/null +++ b/crates/it-types/src/values.rs @@ -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), + + //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), +} + +impl Default for InterfaceValue { + fn default() -> Self { + Self::I32(0) + } +} diff --git a/src/vec1.rs b/crates/it-types/src/vec1.rs similarity index 100% rename from src/vec1.rs rename to crates/it-types/src/vec1.rs diff --git a/src/values.rs b/src/values.rs deleted file mode 100644 index 1322ae3..0000000 --- a/src/values.rs +++ /dev/null @@ -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), - - //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), -} - -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 { - 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>, -} - -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 { - 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 - ] - }) - ); - } -} diff --git a/wasmer-it/Cargo.toml b/wasmer-it/Cargo.toml new file mode 100644 index 0000000..fd39247 --- /dev/null +++ b/wasmer-it/Cargo.toml @@ -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 "] +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"] diff --git a/src/ast.rs b/wasmer-it/src/ast.rs similarity index 94% rename from src/ast.rs rename to wasmer-it/src/ast.rs index 1e6415a..28ad538 100644 --- a/src/ast.rs +++ b/wasmer-it/src/ast.rs @@ -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>, /// Types for the results (`(result …)`). - output_types: Rc>, + output_types: Rc>, }, /// A record type, like: @@ -52,7 +54,7 @@ pub enum Type { /// ```wasm,ignore /// (@interface type (record string i32)) /// ``` - Record(Rc), + Record(Rc), } /// 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, diff --git a/src/decoders/binary.rs b/wasmer-it/src/decoders/binary.rs similarity index 93% rename from src/decoders/binary.rs rename to wasmer-it/src/decoders/binary.rs index f28929a..4ff3c3a 100644 --- a/src/decoders/binary.rs +++ b/wasmer-it/src/decoders/binary.rs @@ -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", diff --git a/src/decoders/mod.rs b/wasmer-it/src/decoders/mod.rs similarity index 100% rename from src/decoders/mod.rs rename to wasmer-it/src/decoders/mod.rs diff --git a/src/decoders/wat.rs b/wasmer-it/src/decoders/wat.rs similarity index 92% rename from src/decoders/wat.rs rename to wasmer-it/src/decoders/wat.rs index 98fb16c..8fe9071 100644 --- a/src/decoders/wat.rs +++ b/wasmer-it/src/decoders/wat.rs @@ -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 { +impl Parse<'_> for ITypeImpl { + fn parse(parser: Parser<'_>) -> Result { let mut lookahead = parser.lookahead1(); if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::S8) + Ok(IType::S8) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::S16) + Ok(IType::S16) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::S32) + Ok(IType::S32) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::S64) + Ok(IType::S64) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::U8) + Ok(IType::U8) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::U16) + Ok(IType::U16) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::U32) + Ok(IType::U32) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::U64) + Ok(IType::U64) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::F32) + Ok(IType::F32) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::F64) + Ok(IType::F64) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::String) + Ok(IType::String) } else if lookahead.peek::() { parser.parse::()?; 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::() { parser.parse::()?; - Ok(InterfaceType::Anyref) + Ok(IType::Anyref) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::I32) + Ok(IType::I32) } else if lookahead.peek::() { parser.parse::()?; - Ok(InterfaceType::I64) + Ok(IType::I64) } else if lookahead.peek::() { parser.parse::()?; - 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 { parser.parse::()?; @@ -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), - Output(Vec), + Output(Vec), } 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::(&buffer(input)).unwrap(), - output - ); + assert_eq!(&parser::parse::(&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::(&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::(&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::(&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::(&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", diff --git a/src/encoders/binary.rs b/wasmer-it/src/encoders/binary.rs similarity index 94% rename from src/encoders/binary.rs rename to wasmer-it/src/encoders/binary.rs index 991643d..3cade0e 100644 --- a/src/encoders/binary.rs +++ b/wasmer-it/src/encoders/binary.rs @@ -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 where @@ -106,31 +111,31 @@ where } /// Encode an `InterfaceType` into bytes. -impl ToBytes for InterfaceType +impl ToBytes 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 ToBytes for RecordFieldType +impl ToBytes 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 ToBytes for RecordType +impl ToBytes 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) } } diff --git a/src/encoders/mod.rs b/wasmer-it/src/encoders/mod.rs similarity index 100% rename from src/encoders/mod.rs rename to wasmer-it/src/encoders/mod.rs diff --git a/src/encoders/wat.rs b/wasmer-it/src/encoders/wat.rs similarity index 92% rename from src/encoders/wat.rs rename to wasmer-it/src/encoders/wat.rs index 5ec7f79..c921c8f 100644 --- a/src/encoders/wat.rs +++ b/wasmer-it/src/encoders/wat.rs @@ -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 { diff --git a/src/errors.rs b/wasmer-it/src/errors.rs similarity index 100% rename from src/errors.rs rename to wasmer-it/src/errors.rs diff --git a/src/interpreter/instructions/argument_get.rs b/wasmer-it/src/interpreter/instructions/argument_get.rs similarity index 100% rename from src/interpreter/instructions/argument_get.rs rename to wasmer-it/src/interpreter/instructions/argument_get.rs diff --git a/src/interpreter/instructions/arrays.rs b/wasmer-it/src/interpreter/instructions/arrays.rs similarity index 100% rename from src/interpreter/instructions/arrays.rs rename to wasmer-it/src/interpreter/instructions/arrays.rs diff --git a/src/interpreter/instructions/call_core.rs b/wasmer-it/src/interpreter/instructions/call_core.rs similarity index 100% rename from src/interpreter/instructions/call_core.rs rename to wasmer-it/src/interpreter/instructions/call_core.rs diff --git a/src/interpreter/instructions/dup.rs b/wasmer-it/src/interpreter/instructions/dup.rs similarity index 100% rename from src/interpreter/instructions/dup.rs rename to wasmer-it/src/interpreter/instructions/dup.rs diff --git a/src/interpreter/instructions/mod.rs b/wasmer-it/src/interpreter/instructions/mod.rs similarity index 100% rename from src/interpreter/instructions/mod.rs rename to wasmer-it/src/interpreter/instructions/mod.rs diff --git a/src/interpreter/instructions/numbers.rs b/wasmer-it/src/interpreter/instructions/numbers.rs similarity index 100% rename from src/interpreter/instructions/numbers.rs rename to wasmer-it/src/interpreter/instructions/numbers.rs diff --git a/src/interpreter/instructions/records.rs b/wasmer-it/src/interpreter/instructions/records.rs similarity index 99% rename from src/interpreter/instructions/records.rs rename to wasmer-it/src/interpreter/instructions/records.rs index bbc7681..4092d35 100644 --- a/src/interpreter/instructions/records.rs +++ b/wasmer-it/src/interpreter/instructions/records.rs @@ -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()); } diff --git a/src/interpreter/instructions/strings.rs b/wasmer-it/src/interpreter/instructions/strings.rs similarity index 100% rename from src/interpreter/instructions/strings.rs rename to wasmer-it/src/interpreter/instructions/strings.rs diff --git a/src/interpreter/instructions/swap2.rs b/wasmer-it/src/interpreter/instructions/swap2.rs similarity index 100% rename from src/interpreter/instructions/swap2.rs rename to wasmer-it/src/interpreter/instructions/swap2.rs diff --git a/src/interpreter/instructions/utils.rs b/wasmer-it/src/interpreter/instructions/utils.rs similarity index 100% rename from src/interpreter/instructions/utils.rs rename to wasmer-it/src/interpreter/instructions/utils.rs diff --git a/src/interpreter/mod.rs b/wasmer-it/src/interpreter/mod.rs similarity index 100% rename from src/interpreter/mod.rs rename to wasmer-it/src/interpreter/mod.rs diff --git a/src/interpreter/stack.rs b/wasmer-it/src/interpreter/stack.rs similarity index 100% rename from src/interpreter/stack.rs rename to wasmer-it/src/interpreter/stack.rs diff --git a/src/interpreter/wasm/mod.rs b/wasmer-it/src/interpreter/wasm/mod.rs similarity index 100% rename from src/interpreter/wasm/mod.rs rename to wasmer-it/src/interpreter/wasm/mod.rs diff --git a/src/interpreter/wasm/structures.rs b/wasmer-it/src/interpreter/wasm/structures.rs similarity index 100% rename from src/interpreter/wasm/structures.rs rename to wasmer-it/src/interpreter/wasm/structures.rs diff --git a/src/lib.rs b/wasmer-it/src/lib.rs similarity index 85% rename from src/lib.rs rename to wasmer-it/src/lib.rs index a9eda2f..783f940 100644 --- a/src/lib.rs +++ b/wasmer-it/src/lib.rs @@ -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); diff --git a/src/macros.rs b/wasmer-it/src/macros.rs similarity index 100% rename from src/macros.rs rename to wasmer-it/src/macros.rs diff --git a/src/serde/de.rs b/wasmer-it/src/serde/de.rs similarity index 80% rename from src/serde/de.rs rename to wasmer-it/src/serde/de.rs index d756ad6..b489f07 100644 --- a/src/serde/de.rs +++ b/wasmer-it/src/serde/de.rs @@ -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::(&values).unwrap(); /// @@ -52,7 +49,7 @@ use std::{ /// } /// ); /// ``` -pub fn from_interface_values<'a, T>(values: &'a [InterfaceValue]) -> Result +pub fn from_interface_values<'a, T>(values: &'a [IValue]) -> Result 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>, + iterator: Peekable>, } 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::(&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::(&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::(&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 }, diff --git a/src/serde/mod.rs b/wasmer-it/src/serde/mod.rs similarity index 100% rename from src/serde/mod.rs rename to wasmer-it/src/serde/mod.rs diff --git a/src/serde/ser.rs b/wasmer-it/src/serde/ser.rs similarity index 87% rename from src/serde/ser.rs rename to wasmer-it/src/serde/ser.rs index 84d5109..add64dd 100644 --- a/src/serde/ser.rs +++ b/wasmer-it/src/serde/ser.rs @@ -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(value: &T) -> Result +pub fn to_interface_value(value: &T) -> Result 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>, + values: Vec>, } impl Serializer { @@ -78,7 +81,7 @@ impl Serializer { } } - fn last(&mut self) -> &mut Vec { + fn last(&mut self) -> &mut Vec { self.values.last_mut().unwrap() } @@ -86,7 +89,7 @@ impl Serializer { self.values.push(Vec::with_capacity(capacity)); } - fn pop(&mut self) -> Result, SerializeError> { + fn pop(&mut self) -> Result, 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 { - let record = InterfaceValue::Record( - Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?, - ); + let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); + + 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 { - let record = InterfaceValue::Record( - Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?, - ); + let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); + + 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 { - let record = InterfaceValue::Record( - Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?, - ); + let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); + + 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 { - let record = InterfaceValue::Record( - Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?, - ); + let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); + + 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); diff --git a/wasmer-it/src/values.rs b/wasmer-it/src/values.rs new file mode 100644 index 0000000..db652d7 --- /dev/null +++ b/wasmer-it/src/values.rs @@ -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 { + 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>, +} + +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 { + 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, + } + } +} From 3ca9734d2e50fe9574ada5441ef104532dfa7aa0 Mon Sep 17 00:00:00 2001 From: vms Date: Mon, 28 Dec 2020 22:33:58 +0300 Subject: [PATCH 3/7] update --- Cargo.lock | 18 +- crates/it-types/Cargo.toml | 7 + crates/it-types/src/impls/errors.rs | 29 +++ crates/it-types/src/impls/mod.rs | 6 + crates/it-types/src/impls/types.rs | 161 +++++++++++++ crates/it-types/src/impls/values.rs | 51 +++++ crates/it-types/src/lib.rs | 15 +- crates/it-types/src/{vec1.rs => ne_vec.rs} | 21 +- crates/it-types/src/types.rs | 60 ++++- crates/it-types/src/values.rs | 10 +- tests/binary.rs | 6 +- wasmer-it/Cargo.toml | 2 +- wasmer-it/src/ast.rs | 7 +- wasmer-it/src/decoders/binary.rs | 18 +- wasmer-it/src/decoders/wat.rs | 139 +----------- wasmer-it/src/encoders/binary.rs | 214 ++++++++++-------- wasmer-it/src/encoders/wat.rs | 119 +++------- wasmer-it/src/errors.rs | 41 +--- .../interpreter/instructions/argument_get.rs | 14 +- .../src/interpreter/instructions/arrays.rs | 135 +++++------ .../src/interpreter/instructions/call_core.rs | 34 +-- wasmer-it/src/interpreter/instructions/mod.rs | 126 ++++++----- .../src/interpreter/instructions/numbers.rs | 148 ++++++------ .../src/interpreter/instructions/records.rs | 135 +++++------ .../src/interpreter/instructions/strings.rs | 66 +++--- .../src/interpreter/instructions/utils.rs | 14 +- wasmer-it/src/interpreter/mod.rs | 30 ++- wasmer-it/src/interpreter/wasm/structures.rs | 25 +- wasmer-it/src/lib.rs | 11 +- wasmer-it/src/macros.rs | 12 +- wasmer-it/src/serde/de.rs | 8 +- wasmer-it/src/serde/ser.rs | 45 ++-- wasmer-it/src/values.rs | 53 +---- 33 files changed, 919 insertions(+), 861 deletions(-) create mode 100644 crates/it-types/src/impls/errors.rs create mode 100644 crates/it-types/src/impls/mod.rs create mode 100644 crates/it-types/src/impls/types.rs create mode 100644 crates/it-types/src/impls/values.rs rename crates/it-types/src/{vec1.rs => ne_vec.rs} (70%) diff --git a/Cargo.lock b/Cargo.lock index 481211e..3c185a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/crates/it-types/Cargo.toml b/crates/it-types/Cargo.toml index ca30c9f..64019ad 100644 --- a/crates/it-types/Cargo.toml +++ b/crates/it-types/Cargo.toml @@ -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"] diff --git a/crates/it-types/src/impls/errors.rs b/crates/it-types/src/impls/errors.rs new file mode 100644 index 0000000..4f77bd0 --- /dev/null +++ b/crates/it-types/src/impls/errors.rs @@ -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) + } +} diff --git a/crates/it-types/src/impls/mod.rs b/crates/it-types/src/impls/mod.rs new file mode 100644 index 0000000..b6eb852 --- /dev/null +++ b/crates/it-types/src/impls/mod.rs @@ -0,0 +1,6 @@ +mod errors; +mod types; +mod values; + +pub use errors::WasmValueNativeCastError; +pub use values::NativeType; diff --git a/crates/it-types/src/impls/types.rs b/crates/it-types/src/impls/types.rs new file mode 100644 index 0000000..ea74054 --- /dev/null +++ b/crates/it-types/src/impls/types.rs @@ -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 { + let mut lookahead = parser.lookahead1(); + if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::S8) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::S16) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::S32) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::S64) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::U8) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::U16) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::U32) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::U64) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::F32) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::F64) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::String) + } else if lookahead.peek::() { + parser.parse::()?; + + let array_type = parser.parens(|p| p.parse())?; + + Ok(IType::Array(Box::new(array_type))) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::Anyref) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::I32) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::I64) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::Record(parser.parse()?)) + } else { + Err(lookahead.error()) + } + } +} + +impl Parse<'_> for IRecordType { + fn parse(parser: Parser<'_>) -> Result { + parser.parse::()?; + + 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::()?; + + 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) + } +} diff --git a/crates/it-types/src/impls/values.rs b/crates/it-types/src/impls/values.rs new file mode 100644 index 0000000..3d99b2e --- /dev/null +++ b/crates/it-types/src/impls/values.rs @@ -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 { + 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); diff --git a/crates/it-types/src/lib.rs b/crates/it-types/src/lib.rs index 893c264..f304e07 100644 --- a/crates/it-types/src/lib.rs +++ b/crates/it-types/src/lib.rs @@ -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; diff --git a/crates/it-types/src/vec1.rs b/crates/it-types/src/ne_vec.rs similarity index 70% rename from crates/it-types/src/vec1.rs rename to crates/it-types/src/ne_vec.rs index 360a3e3..a7ce992 100644 --- a/crates/it-types/src/vec1.rs +++ b/crates/it-types/src/ne_vec.rs @@ -1,4 +1,4 @@ -//! `Vec1` represents a non-empty `Vec`. +//! `NEVec` represents a non-empty `Vec`. use serde::{Deserialize, Serialize}; use std::{ @@ -7,14 +7,14 @@ use std::{ ops, }; -/// `Vec1` represents a non-empty `Vec`. It derefs to `Vec` +/// `NEVec` represents a non-empty `Vec`. It derefs to `Vec` /// directly. #[derive(Clone, PartialEq, Eq, Serialize, Hash, Deserialize, Default)] -pub struct Vec1(Vec) +pub struct NEVec(Vec) 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 Vec1 +impl NEVec where T: Debug, { @@ -41,13 +44,13 @@ where } } - /// Converts this Vec1 into Vec + /// Converts this NEVec into Vec pub fn into_vec(self) -> Vec { self.0 } } -impl fmt::Debug for Vec1 +impl fmt::Debug for NEVec where T: Debug, { @@ -56,7 +59,7 @@ where } } -impl ops::Deref for Vec1 +impl ops::Deref for NEVec where T: Debug, { diff --git a/crates/it-types/src/types.rs b/crates/it-types/src/types.rs index 3310ebe..70ca577 100644 --- a/crates/it-types/src/types.rs +++ b/crates/it-types/src/types.rs @@ -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), + Array(Box), /// 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, + pub fields: NEVec, } 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 + }), + ) + } +} diff --git a/crates/it-types/src/values.rs b/crates/it-types/src/values.rs index 7b765f4..a2835f2 100644 --- a/crates/it-types/src/values.rs +++ b/crates/it-types/src/values.rs @@ -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), + Array(Vec), //Anyref(?), /// A 32-bits integer (as defined in WebAssembly core). @@ -49,10 +49,10 @@ pub enum InterfaceValue { I64(i64), /// A record. - Record(Vec1), + Record(NEVec), } -impl Default for InterfaceValue { +impl Default for IValue { fn default() -> Self { Self::I32(0) } diff --git a/tests/binary.rs b/tests/binary.rs index 8198c04..271585b 100644 --- a/tests/binary.rs +++ b/tests/binary.rs @@ -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 { diff --git a/wasmer-it/Cargo.toml b/wasmer-it/Cargo.toml index fd39247..7a7131a 100644 --- a/wasmer-it/Cargo.toml +++ b/wasmer-it/Cargo.toml @@ -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" diff --git a/wasmer-it/src/ast.rs b/wasmer-it/src/ast.rs index 28ad538..e332ce0 100644 --- a/wasmer-it/src/ast.rs +++ b/wasmer-it/src/ast.rs @@ -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; diff --git a/wasmer-it/src/decoders/binary.rs b/wasmer-it/src/decoders/binary.rs index 4ff3c3a..77482ff 100644 --- a/wasmer-it/src/decoders/binary.rs +++ b/wasmer-it/src/decoders/binary.rs @@ -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."), }, )) } diff --git a/wasmer-it/src/decoders/wat.rs b/wasmer-it/src/decoders/wat.rs index 8fe9071..668a30f 100644 --- a/wasmer-it/src/decoders/wat.rs +++ b/wasmer-it/src/decoders/wat.rs @@ -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 { - let mut lookahead = parser.lookahead1(); - if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::S8) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::S16) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::S32) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::S64) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::U8) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::U16) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::U32) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::U64) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::F32) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::F64) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::String) - } else if lookahead.peek::() { - parser.parse::()?; - - let array_type = parser.parens(|p| p.parse())?; - - Ok(IType::Array(Box::new(array_type))) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::Anyref) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::I32) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::I64) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::Record(parser.parse()?)) - } else { - Err(lookahead.error()) - } - } -} - -impl Parse<'_> for RecordTypeImpl { - fn parse(parser: Parser<'_>) -> Result { - parser.parse::()?; - - 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::()?; - - 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)] diff --git a/wasmer-it/src/encoders/binary.rs b/wasmer-it/src/encoders/binary.rs index 3cade0e..c55dcba 100644 --- a/wasmer-it/src/encoders/binary.rs +++ b/wasmer-it/src/encoders/binary.rs @@ -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 @@ -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 ToBytes for u8 where @@ -53,6 +64,72 @@ where } } +/// Encode an `IType` into bytes. +impl ToBytes 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 ToBytes 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 ToBytes 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::>(); + + 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 ToBytes 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 ToBytes 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 ToBytes 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 ToBytes 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::>(); 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", diff --git a/wasmer-it/src/encoders/wat.rs b/wasmer-it/src/encoders/wat.rs index c921c8f..cff8aa1 100644 --- a/wasmer-it/src/encoders/wat.rs +++ b/wasmer-it/src/encoders/wat.rs @@ -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 = 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 = 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", diff --git a/wasmer-it/src/errors.rs b/wasmer-it/src/errors.rs index 845a4f0..215e291 100644 --- a/wasmer-it/src/errors.rs +++ b/wasmer-it/src/errors.rs @@ -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 = Result; /// A type alias for the interpreter result. pub type InterpreterResult = Result; -/// 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, Vec), + expected: (Vec, Vec), /// The received signature. - received: (Vec, Vec), + received: (Vec, Vec), }, /// Failed to call a local or import function. diff --git a/wasmer-it/src/interpreter/instructions/argument_get.rs b/wasmer-it/src/interpreter/instructions/argument_get.rs index f8a8c7e..35825e4 100644 --- a/wasmer-it/src/interpreter/instructions/argument_get.rs +++ b/wasmer-it/src/interpreter/instructions/argument_get.rs @@ -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" ); diff --git a/wasmer-it/src/interpreter/instructions/arrays.rs b/wasmer-it/src/interpreter/instructions/arrays.rs index 87198c7..32482e0 100644 --- a/wasmer-it/src/interpreter/instructions/arrays.rs +++ b/wasmer-it/src/interpreter/instructions/arrays.rs @@ -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, InstructionError> +) -> Result, 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::(data).unwrap(); - data.into_iter().map(InterfaceValue::S8).collect::>() + data.into_iter().map(IValue::S8).collect::>() } - InterfaceType::S16 => { + IType::S16 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::S16(*v)) - .collect::>() + data.iter().map(|v| IValue::S16(*v)).collect::>() } - InterfaceType::S32 => { + IType::S32 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::S32(*v)) - .collect::>() + data.iter().map(|v| IValue::S32(*v)).collect::>() } - InterfaceType::S64 => { + IType::S64 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::S64(*v)) - .collect::>() + data.iter().map(|v| IValue::S64(*v)).collect::>() } - InterfaceType::I32 => { + IType::I32 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::I32(*v)) - .collect::>() + data.iter().map(|v| IValue::I32(*v)).collect::>() } - InterfaceType::I64 => { + IType::I64 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::S64(*v)) - .collect::>() + data.iter().map(|v| IValue::S64(*v)).collect::>() } - InterfaceType::U8 => data.into_iter().map(InterfaceValue::U8).collect::>(), - InterfaceType::U16 => { + IType::U8 => data.into_iter().map(IValue::U8).collect::>(), + IType::U16 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::U16(*v)) - .collect::>() + data.iter().map(|v| IValue::U16(*v)).collect::>() } - InterfaceType::U32 => { + IType::U32 => { + let data = transmute_many::(&data).unwrap(); + data.iter().map(|v| IValue::U32(*v)).collect::>() + } + IType::U64 => { + let data = transmute_many::(&data).unwrap(); + data.iter().map(|v| IValue::U64(*v)).collect::>() + } + IType::F32 => { let data = transmute_many::(&data).unwrap(); data.iter() - .map(|v| InterfaceValue::U32(*v)) + .map(|v| IValue::F32(f32::from_bits(*v))) .collect::>() } - InterfaceType::U64 => { + IType::F64 => { let data = transmute_many::(&data).unwrap(); data.iter() - .map(|v| InterfaceValue::U64(*v)) + .map(|v| IValue::F64(f64::from_bits(*v))) .collect::>() } - InterfaceType::F32 => { - let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::F32(f32::from_bits(*v))) - .collect::>() - } - InterfaceType::F64 => { - let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::F64(f64::from_bits(*v))) - .collect::>() - } - InterfaceType::Anyref => unimplemented!(), - InterfaceType::String => { + IType::Anyref => unimplemented!(), + IType::String => { let data = transmute_many::(&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::(&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( instruction: Instruction, - value_type: InterfaceType, + value_type: IType, ) -> crate::interpreter::ExecutableInstruction 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: &mut Instance, instruction: Instruction, - array_values: Vec, + array_values: Vec, ) -> 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( instruction: Instruction, - value_type: InterfaceType, + value_type: IType, ) -> crate::interpreter::ExecutableInstruction 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(), }, )), diff --git a/wasmer-it/src/interpreter/instructions/call_core.rs b/wasmer-it/src/interpreter/instructions/call_core.rs index 1785a7e..4703249 100644 --- a/wasmer-it/src/interpreter/instructions/call_core.rs +++ b/wasmer-it/src/interpreter/instructions/call_core.rs @@ -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 }, diff --git a/wasmer-it/src/interpreter/instructions/mod.rs b/wasmer-it/src/interpreter/instructions/mod.rs index 994bfce..aaf5d46 100644 --- a/wasmer-it/src/interpreter/instructions/mod.rs +++ b/wasmer-it/src/interpreter/instructions/mod.rs @@ -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 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, { 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, - pub(crate) outputs: Vec, - pub(crate) function: fn(arguments: &[InterfaceValue]) -> Result, ()>, + pub(crate) inputs: Vec, + pub(crate) outputs: Vec, + pub(crate) function: fn(arguments: &[IValue]) -> Result, ()>, } 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, ()> { + fn call(&self, arguments: &[IValue]) -> Result, ()> { (self.function)(arguments) } } pub(crate) struct LocalImport { - pub(crate) inputs: Vec, - pub(crate) outputs: Vec, - pub(crate) function: fn(arguments: &[InterfaceValue]) -> Result, ()>, + pub(crate) inputs: Vec, + pub(crate) outputs: Vec, + pub(crate) function: fn(arguments: &[IValue]) -> Result, ()>, } 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, ()> { + fn call(&self, arguments: &[IValue]) -> Result, ()> { (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, } ], })], diff --git a/wasmer-it/src/interpreter/instructions/numbers.rs b/wasmer-it/src/interpreter/instructions/numbers.rs index 0d3d0f7..a85c109 100644 --- a/wasmer-it/src/interpreter/instructions/numbers.rs +++ b/wasmer-it/src/interpreter/instructions/numbers.rs @@ -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)], ); } diff --git a/wasmer-it/src/interpreter/instructions/records.rs b/wasmer-it/src/interpreter/instructions/records.rs index 4092d35..99f3b38 100644 --- a/wasmer-it/src/interpreter/instructions/records.rs +++ b/wasmer-it/src/interpreter/instructions/records.rs @@ -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, + stack: &mut Stack, record_type: &RecordType, -) -> Result { +) -> Result { 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 +) -> Result where Export: crate::interpreter::wasm::structures::Export, LocalImport: crate::interpreter::wasm::structures::LocalImport, @@ -113,12 +114,12 @@ where Instance: crate::interpreter::wasm::structures::Instance + '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: &mut Instance, instruction: Instruction, - values: Vec1, + values: NEVec, ) -> Result 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(), }, )), diff --git a/wasmer-it/src/interpreter/instructions/strings.rs b/wasmer-it/src/interpreter/instructions/strings.rs index d6ede4d..d8ffed6 100644 --- a/wasmer-it/src/interpreter/instructions/strings.rs +++ b/wasmer-it/src/interpreter/instructions/strings.rs @@ -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"#, ); diff --git a/wasmer-it/src/interpreter/instructions/utils.rs b/wasmer-it/src/interpreter/instructions/utils.rs index ac099ae..0e7fd18 100644 --- a/wasmer-it/src/interpreter/instructions/utils.rs +++ b/wasmer-it/src/interpreter/instructions/utils.rs @@ -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, -) -> Result, InstructionError> + inputs: Vec, +) -> Result, InstructionError> where Export: wasm::structures::Export + 'instance, LocalImport: wasm::structures::LocalImport + 'instance, diff --git a/wasmer-it/src/interpreter/mod.rs b/wasmer-it/src/interpreter/mod.rs index 37a106e..9c023aa 100644 --- a/wasmer-it/src/interpreter/mod.rs +++ b/wasmer-it/src/interpreter/mod.rs @@ -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, + stack: Stack, /// The WebAssembly module instance. It is used by adapter's /// instructions. @@ -68,8 +66,8 @@ pub(crate) type ExecutableInstruction where @@ -158,9 +156,9 @@ where /// returns the stack. pub fn run( &self, - invocation_inputs: &[InterfaceValue], + invocation_inputs: &[IValue], wasm_instance: &mut Instance, - ) -> InterpreterResult> { + ) -> InterpreterResult> { let mut runtime = Runtime { invocation_inputs, stack: Stack::new(), diff --git a/wasmer-it/src/interpreter/wasm/structures.rs b/wasmer-it/src/interpreter/wasm/structures.rs index cb7c92e..4666a75 100644 --- a/wasmer-it/src/interpreter/wasm/structures.rs +++ b/wasmer-it/src/interpreter/wasm/structures.rs @@ -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, ()>; + fn outputs(&self) -> &[IType]; + fn call(&self, arguments: &[IValue]) -> Result, ()>; } 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, ()>; + fn outputs(&self) -> &[IType]; + fn call(&self, arguments: &[IValue]) -> Result, ()>; } pub trait MemoryView: Deref]> {} @@ -79,7 +80,7 @@ where fn export(&self, export_name: &str) -> Option<&E>; fn local_or_import(&self, index: I) -> Option<&LI>; fn memory(&self, index: usize) -> Option<&M>; - fn wit_record_by_id(&self, index: u64) -> Option<&Rc>; + fn wit_record_by_id(&self, index: u64) -> Option<&Rc>; } impl Export for () { @@ -99,11 +100,11 @@ impl Export for () { &[] } - fn outputs(&self) -> &[InterfaceType] { + fn outputs(&self) -> &[IType] { &[] } - fn call(&self, _arguments: &[InterfaceValue]) -> Result, ()> { + fn call(&self, _arguments: &[IValue]) -> Result, ()> { Err(()) } } @@ -125,11 +126,11 @@ impl LocalImport for () { &[] } - fn outputs(&self) -> &[InterfaceType] { + fn outputs(&self) -> &[IType] { &[] } - fn call(&self, _arguments: &[InterfaceValue]) -> Result, ()> { + fn call(&self, _arguments: &[IValue]) -> Result, ()> { Err(()) } } @@ -171,7 +172,7 @@ where None } - fn wit_record_by_id(&self, _index: u64) -> Option<&Rc> { + fn wit_record_by_id(&self, _index: u64) -> Option<&Rc> { None } } diff --git a/wasmer-it/src/lib.rs b/wasmer-it/src/lib.rs index 783f940..21eb67a 100644 --- a/wasmer-it/src/lib.rs +++ b/wasmer-it/src/lib.rs @@ -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; diff --git a/wasmer-it/src/macros.rs b/wasmer-it/src/macros.rs index 08f57c9..baf976e 100644 --- a/wasmer-it/src/macros.rs +++ b/wasmer-it/src/macros.rs @@ -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}; diff --git a/wasmer-it/src/serde/de.rs b/wasmer-it/src/serde/de.rs index b489f07..2729615 100644 --- a/wasmer-it/src/serde/de.rs +++ b/wasmer-it/src/serde/de.rs @@ -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::(&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>, } 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(), } diff --git a/wasmer-it/src/serde/ser.rs b/wasmer-it/src/serde/ser.rs index add64dd..06c353b 100644 --- a/wasmer-it/src/serde/ser.rs +++ b/wasmer-it/src/serde/ser.rs @@ -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>, + values: Vec>, } impl Serializer { @@ -81,7 +79,7 @@ impl Serializer { } } - fn last(&mut self) -> &mut Vec { + fn last(&mut self) -> &mut Vec { self.values.last_mut().unwrap() } @@ -89,7 +87,7 @@ impl Serializer { self.values.push(Vec::with_capacity(capacity)); } - fn pop(&mut self) -> Result, SerializeError> { + fn pop(&mut self) -> Result, 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 { - let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); - - 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 { - let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); - - 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 { - let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); - - 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 { - let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); - - 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(()) diff --git a/wasmer-it/src/values.rs b/wasmer-it/src/values.rs index db652d7..9885d65 100644 --- a/wasmer-it/src/values.rs +++ b/wasmer-it/src/values.rs @@ -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 { - 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)`. From b8ca78047358f9e87c3090fa3c463c10e1dbf7fe Mon Sep 17 00:00:00 2001 From: vms Date: Tue, 29 Dec 2020 11:30:47 +0300 Subject: [PATCH 4/7] bump version --- Cargo.lock | 6 +++--- wasmer-it/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c185a1..2093188 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,9 +130,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" +checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" dependencies = [ "itoa", "ryu", @@ -170,7 +170,7 @@ checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "wasmer-interface-types-fl" -version = "0.17.20" +version = "0.17.21" dependencies = [ "fluence-it-types", "log", diff --git a/wasmer-it/Cargo.toml b/wasmer-it/Cargo.toml index 7a7131a..2032475 100644 --- a/wasmer-it/Cargo.toml +++ b/wasmer-it/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-interface-types-fl" -version = "0.17.20" +version = "0.17.21" description = "WebAssembly Interface Types library for Wasmer" license = "MIT" authors = ["The Wasmer Engineering Team "] From ffbe1a282a7dea97066b7a83d1e916b92dd3090b Mon Sep 17 00:00:00 2001 From: vms Date: Tue, 29 Dec 2020 12:32:17 +0300 Subject: [PATCH 5/7] decouple ToBytes into a separate crate --- Cargo.lock | 8 +- Cargo.toml | 1 + crates/it-types/Cargo.toml | 4 +- crates/it-types/src/impls/types.rs | 59 +++++ crates/to-bytes/Cargo.toml | 7 + crates/to-bytes/src/lib.rs | 104 +++++++++ wasmer-it/Cargo.toml | 1 + wasmer-it/src/encoders/binary.rs | 201 +----------------- .../src/interpreter/instructions/records.rs | 12 ++ 9 files changed, 201 insertions(+), 196 deletions(-) create mode 100644 crates/to-bytes/Cargo.toml create mode 100644 crates/to-bytes/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 2093188..4950fa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,13 +20,18 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "fluence-it-types" -version = "0.1.0" +version = "0.1.1" dependencies = [ + "it-to-bytes", "nom", "serde", "wast", ] +[[package]] +name = "it-to-bytes" +version = "0.1.0" + [[package]] name = "itoa" version = "0.4.7" @@ -173,6 +178,7 @@ name = "wasmer-interface-types-fl" version = "0.17.21" dependencies = [ "fluence-it-types", + "it-to-bytes", "log", "nom", "safe-transmute", diff --git a/Cargo.toml b/Cargo.toml index 196e565..1190f48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "crates/to-bytes", "crates/it-types", "wasmer-it", ] diff --git a/crates/it-types/Cargo.toml b/crates/it-types/Cargo.toml index 64019ad..1d868d6 100644 --- a/crates/it-types/Cargo.toml +++ b/crates/it-types/Cargo.toml @@ -1,12 +1,14 @@ [package] name = "fluence-it-types" -version = "0.1.0" +version = "0.1.1" description = "Definitions of IValue and IType" authors = ["Fluence Labs"] edition = "2018" license = "Apache-2.0" [dependencies] +it-to-bytes = { path = "../to-bytes/", version = "0.1.0" } + serde = { version = "1.0.118", features = ["derive", "rc"]} nom = { version = "5.1", optional = true } diff --git a/crates/it-types/src/impls/types.rs b/crates/it-types/src/impls/types.rs index ea74054..963818a 100644 --- a/crates/it-types/src/impls/types.rs +++ b/crates/it-types/src/impls/types.rs @@ -3,10 +3,69 @@ use crate::IRecordFieldType; use crate::IRecordType; use crate::IType; +use it_to_bytes::ToBytes; use wast::parser::Parse; use wast::parser::Parser; use wast::Error as ParseError; +use std::io; +use std::io::Write; + +/// Encode an `IType` into bytes. +impl ToBytes for IType +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + match self { + 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 ToBytes for IRecordFieldType +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + self.name.as_str().to_bytes(writer)?; + self.ty.to_bytes(writer) + } +} + +/// Encode a `RecordType` into bytes. +impl ToBytes for IRecordType +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + self.name.as_str().to_bytes(writer)?; + self.fields.to_bytes(writer) + } +} + mod keyword { pub use wast::{ custom_keyword, diff --git a/crates/to-bytes/Cargo.toml b/crates/to-bytes/Cargo.toml new file mode 100644 index 0000000..4b03d7a --- /dev/null +++ b/crates/to-bytes/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "it-to-bytes" +version = "0.1.0" +authors = ["Fluence Labs"] +description = "Defines trait ToBytes used for IT serialization" +edition = "2018" +license = "Apache-2.0" diff --git a/crates/to-bytes/src/lib.rs b/crates/to-bytes/src/lib.rs new file mode 100644 index 0000000..e35fd8d --- /dev/null +++ b/crates/to-bytes/src/lib.rs @@ -0,0 +1,104 @@ +use std::io; +use std::io::Write; + +/// A trait for converting a value to bytes. +pub trait ToBytes +where + W: Write, +{ + /// Converts the given value into `&[u8]` in the given `writer`. + fn to_bytes(&self, writer: &mut W) -> io::Result<()>; +} + +/// Encode a `u8` into a byte (well, it's already a byte!). +impl ToBytes for u8 +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + writer.write_all(&[*self]) + } +} + +/// Encode a `u64` into bytes with a LEB128 representation. +/// +/// Decoder is `decoders::binary::uleb`. +impl ToBytes for u64 +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + let mut value = *self; + + // Code adapted from the Rust' `serialize` library. + loop { + if value < 0x80 { + writer.write_all(&[value as u8])?; + + break; + } + + writer.write_all(&[((value & 0x7f) | 0x80) as u8])?; + value >>= 7; + } + + Ok(()) + } +} + +/// Encode a `str` into bytes. +/// +/// Decoder is `decoders::binary::string`. +impl ToBytes for &str +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + // Size first. + writer.write_all(&[self.len() as u8])?; + + // Then the string. + writer.write_all(self.as_bytes())?; + + Ok(()) + } +} + +/// Encode a String into bytes. +/// +/// Decoder is `decoders::binary::string`. +impl ToBytes for String +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + // Size first. + writer.write_all(&[self.len() as u8])?; + + // Then the string. + writer.write_all(self.as_bytes())?; + + Ok(()) + } +} + +/// Encode a vector into bytes. +/// +/// Decoder is `decoders::binary::list`. +impl ToBytes for Vec +where + W: Write, + I: ToBytes, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + // Size first. + (self.len() as u64).to_bytes(writer)?; + + // Then the items. + for item in self { + item.to_bytes(writer)?; + } + + Ok(()) + } +} diff --git a/wasmer-it/Cargo.toml b/wasmer-it/Cargo.toml index 2032475..0333a1d 100644 --- a/wasmer-it/Cargo.toml +++ b/wasmer-it/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" [dependencies] fluence-it-types = { path = "../crates/it-types", version = "0.1.0", features = ["impls"] } +it-to-bytes = { path = "../crates/to-bytes", version = "0.1.0" } nom = "5.1" wast = "8.0" diff --git a/wasmer-it/src/encoders/binary.rs b/wasmer-it/src/encoders/binary.rs index c55dcba..260c428 100644 --- a/wasmer-it/src/encoders/binary.rs +++ b/wasmer-it/src/encoders/binary.rs @@ -1,191 +1,12 @@ //! Writes the AST into bytes representing WIT with its binary format. -use crate::{ast::*, interpreter::Instruction}; +use crate::ast::*; +use crate::interpreter::Instruction; -use crate::IRecordFieldType; -use crate::IRecordType; -use crate::IType; +use it_to_bytes::ToBytes; use std::io; use std::io::Write; -use std::ops::Deref; - -/// A trait for converting a value to bytes. -pub trait ToBytes -where - W: Write, -{ - /// Converts the given value into `&[u8]` in the given `writer`. - 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 ToBytes for u8 -where - W: Write, -{ - fn to_bytes(&self, writer: &mut W) -> io::Result<()> { - writer.write_all(&[*self]) - } -} - -/// Encode a `u64` into bytes with a LEB128 representation. -/// -/// Decoder is `decoders::binary::uleb`. -impl ToBytes for u64 -where - W: Write, -{ - fn to_bytes(&self, writer: &mut W) -> io::Result<()> { - let mut value = *self; - - // Code adapted from the Rust' `serialize` library. - loop { - if value < 0x80 { - writer.write_all(&[value as u8])?; - - break; - } - - writer.write_all(&[((value & 0x7f) | 0x80) as u8])?; - value >>= 7; - } - - Ok(()) - } -} - -/// Encode an `IType` into bytes. -impl ToBytes 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 ToBytes 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 ToBytes 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::>(); - - record_type_impl.to_bytes(writer) - } -} - -/// Encode a `str` into bytes. -/// -/// Decoder is `decoders::binary::string`. -impl ToBytes for &str -where - W: Write, -{ - fn to_bytes(&self, writer: &mut W) -> io::Result<()> { - // Size first. - writer.write_all(&[self.len() as u8])?; - - // Then the string. - writer.write_all(self.as_bytes())?; - - Ok(()) - } -} - -/// Encode a String into bytes. -/// -/// Decoder is `decoders::binary::string`. -impl ToBytes for String -where - W: Write, -{ - fn to_bytes(&self, writer: &mut W) -> io::Result<()> { - // Size first. - writer.write_all(&[self.len() as u8])?; - - // Then the string. - writer.write_all(self.as_bytes())?; - - Ok(()) - } -} - -/// Encode a vector into bytes. -/// -/// Decoder is `decoders::binary::list`. -impl ToBytes for Vec -where - W: Write, - I: ToBytes, -{ - fn to_bytes(&self, writer: &mut W) -> io::Result<()> { - // Size first. - (self.len() as u64).to_bytes(writer)?; - - // Then the items. - for item in self { - item.to_bytes(writer)?; - } - - Ok(()) - } -} /// Encode a `TypeKind` into bytes. impl ToBytes for TypeKind @@ -222,8 +43,7 @@ where { fn to_bytes(&self, writer: &mut W) -> io::Result<()> { self.name.to_bytes(writer)?; - let itype_impl = ITypeImpl(&self.ty); - itype_impl.to_bytes(writer) + self.ty.to_bytes(writer) } } @@ -242,17 +62,12 @@ where } => { TypeKind::Function.to_bytes(writer)?; arguments.to_bytes(writer)?; - let output_types = output_types - .iter() - .map(|t| ITypeImpl(t)) - .collect::>(); output_types.to_bytes(writer)?; } Type::Record(record_type) => { TypeKind::Record.to_bytes(writer)?; - let record_impl = IRecordTypeImpl(record_type.deref()); - record_impl.to_bytes(writer)?; + record_type.to_bytes(writer)?; } } @@ -416,13 +231,11 @@ where Instruction::ArrayLiftMemory { value_type } => { 0x37_u8.to_bytes(writer)?; - let value_type_impl = ITypeImpl(value_type); - value_type_impl.to_bytes(writer)? + value_type.to_bytes(writer)? } Instruction::ArrayLowerMemory { value_type } => { 0x38_u8.to_bytes(writer)?; - let value_type_impl = ITypeImpl(value_type); - value_type_impl.to_bytes(writer)? + value_type.to_bytes(writer)? } /* Instruction::ArraySize => 0x39_u8.to_bytes(writer)?, diff --git a/wasmer-it/src/interpreter/instructions/records.rs b/wasmer-it/src/interpreter/instructions/records.rs index 99f3b38..f5635e2 100644 --- a/wasmer-it/src/interpreter/instructions/records.rs +++ b/wasmer-it/src/interpreter/instructions/records.rs @@ -12,6 +12,18 @@ use crate::{ }; use std::convert::TryInto; +/* + +struct Record1 { +field1: String, +field2: i32, +} + +// export +fn foo(t: Record1) { + +// import + */ /* /// Build an `IValue::Record` based on values on the stack. From 9afa1e2e15e420425f6e73de8210ab93d1d4cc43 Mon Sep 17 00:00:00 2001 From: vms Date: Tue, 29 Dec 2020 12:41:02 +0300 Subject: [PATCH 6/7] rename FlattenIValues Iterator to FlattenIRecordIterator --- wasmer-it/src/serde/de.rs | 6 +++--- wasmer-it/src/values.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wasmer-it/src/serde/de.rs b/wasmer-it/src/serde/de.rs index 2729615..adc21c1 100644 --- a/wasmer-it/src/serde/de.rs +++ b/wasmer-it/src/serde/de.rs @@ -1,6 +1,6 @@ //! Provides a deserializer from WIT values to Rust value. -use crate::{values::FlattenIValueIterator, IType, IValue}; +use crate::{values::FlattenIRecordIterator, IType, IValue}; use serde::{de, Deserialize}; use std::{ fmt::{self, Display}, @@ -65,13 +65,13 @@ where /// The deserializer. The iterator iterates over `IValue`s, /// all flatten, see `FlattenIValueIterator`. struct Deserializer<'de> { - iterator: Peekable>, + iterator: Peekable>, } impl<'de> Deserializer<'de> { pub fn new(input: &'de [IValue]) -> Deserializer<'de> { Deserializer { - iterator: FlattenIValueIterator::new(input).peekable(), + iterator: FlattenIRecordIterator::new(input).peekable(), } } } diff --git a/wasmer-it/src/values.rs b/wasmer-it/src/values.rs index 9885d65..e4ac751 100644 --- a/wasmer-it/src/values.rs +++ b/wasmer-it/src/values.rs @@ -8,11 +8,11 @@ pub use crate::serde::{de::from_interface_values, ser::to_interface_value}; /// 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> { +pub(crate) struct FlattenIRecordIterator<'a> { iterators: Vec>, } -impl<'a> FlattenIValueIterator<'a> { +impl<'a> FlattenIRecordIterator<'a> { pub(crate) fn new(values: &'a [IValue]) -> Self { Self { iterators: vec![values.iter()], @@ -20,7 +20,7 @@ impl<'a> FlattenIValueIterator<'a> { } } -impl<'a> Iterator for FlattenIValueIterator<'a> { +impl<'a> Iterator for FlattenIRecordIterator<'a> { type Item = &'a IValue; fn next(&mut self) -> Option { From 8442800f5758bb94e2b7a70acf81fe8ac9bf1c3d Mon Sep 17 00:00:00 2001 From: vms Date: Tue, 29 Dec 2020 12:54:18 +0300 Subject: [PATCH 7/7] bump version --- Cargo.lock | 2 +- wasmer-it/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4950fa3..dcab569 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,7 +175,7 @@ checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "wasmer-interface-types-fl" -version = "0.17.21" +version = "0.17.22" dependencies = [ "fluence-it-types", "it-to-bytes", diff --git a/wasmer-it/Cargo.toml b/wasmer-it/Cargo.toml index 0333a1d..0b6bf20 100644 --- a/wasmer-it/Cargo.toml +++ b/wasmer-it/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-interface-types-fl" -version = "0.17.21" +version = "0.17.22" description = "WebAssembly Interface Types library for Wasmer" license = "MIT" authors = ["The Wasmer Engineering Team "]