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, + } + } +}