mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 07:10:21 +00:00
decopule interface
This commit is contained in:
parent
44d559cca1
commit
4b5da87cca
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -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",
|
||||
|
34
Cargo.toml
34
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 <engineering@wasmer.io>"]
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/it-types",
|
||||
"wasmer-it",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
nom = "5.1"
|
||||
wast = "8.0"
|
||||
|
||||
# `serde` is useful only to simplify the users' life. It is not
|
||||
# required by WIT itself, is is used to cross the boundary between the
|
||||
# host and WIT more easily, but it is not used inside Wasm.
|
||||
serde = { version = "1.0", features = ["derive", "rc"], optional = true }
|
||||
serde_json = "1.0"
|
||||
safe-transmute = "0.11.0"
|
||||
log = "0.4.11"
|
||||
|
||||
[features]
|
||||
default = ["serde"]
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
debug = false
|
||||
lto = true
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
panic = "abort"
|
||||
|
9
crates/it-types/Cargo.toml
Normal file
9
crates/it-types/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "fluence-it-types"
|
||||
version = "0.1.0"
|
||||
description = "Definitions of IValue and IType"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.118", features = ["derive", "rc"]}
|
11
crates/it-types/src/lib.rs
Normal file
11
crates/it-types/src/lib.rs
Normal file
@ -0,0 +1,11 @@
|
||||
mod types;
|
||||
mod values;
|
||||
pub mod vec1;
|
||||
|
||||
// types
|
||||
pub use types::InterfaceType as IType;
|
||||
pub use types::RecordFieldType as IRecordFieldType;
|
||||
pub use types::RecordType as IRecordType;
|
||||
|
||||
// values
|
||||
pub use values::InterfaceValue as IValue;
|
@ -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)]
|
59
crates/it-types/src/values.rs
Normal file
59
crates/it-types/src/values.rs
Normal file
@ -0,0 +1,59 @@
|
||||
//! Defines WIT values and associated operations.
|
||||
|
||||
use crate::vec1::Vec1;
|
||||
|
||||
/// A WIT value.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum InterfaceValue {
|
||||
/// A 8-bits signed integer.
|
||||
S8(i8),
|
||||
|
||||
/// A 16-bits signed integer.
|
||||
S16(i16),
|
||||
|
||||
/// A 32-bits signed integer.
|
||||
S32(i32),
|
||||
|
||||
/// A 64-bits signed integer.
|
||||
S64(i64),
|
||||
|
||||
/// A 8-bits unsigned integer.
|
||||
U8(u8),
|
||||
|
||||
/// A 16-bits unsigned integer.
|
||||
U16(u16),
|
||||
|
||||
/// A 32-bits unsigned integer.
|
||||
U32(u32),
|
||||
|
||||
/// A 64-bits unsigned integer.
|
||||
U64(u64),
|
||||
|
||||
/// A 32-bits float.
|
||||
F32(f32),
|
||||
|
||||
/// A 64-bits float.
|
||||
F64(f64),
|
||||
|
||||
/// A string.
|
||||
String(String),
|
||||
|
||||
/// A byte array.
|
||||
Array(Vec<InterfaceValue>),
|
||||
|
||||
//Anyref(?),
|
||||
/// A 32-bits integer (as defined in WebAssembly core).
|
||||
I32(i32),
|
||||
|
||||
/// A 64-bits integer (as defiend in WebAssembly core).
|
||||
I64(i64),
|
||||
|
||||
/// A record.
|
||||
Record(Vec1<InterfaceValue>),
|
||||
}
|
||||
|
||||
impl Default for InterfaceValue {
|
||||
fn default() -> Self {
|
||||
Self::I32(0)
|
||||
}
|
||||
}
|
218
src/values.rs
218
src/values.rs
@ -1,218 +0,0 @@
|
||||
//! Defines WIT values and associated operations.
|
||||
|
||||
use crate::{errors::WasmValueNativeCastError, types::InterfaceType, vec1::Vec1};
|
||||
use std::{convert::TryFrom, slice::Iter};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
pub use crate::serde::{de::from_interface_values, ser::to_interface_value};
|
||||
|
||||
/// A WIT value.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum InterfaceValue {
|
||||
/// A 8-bits signed integer.
|
||||
S8(i8),
|
||||
|
||||
/// A 16-bits signed integer.
|
||||
S16(i16),
|
||||
|
||||
/// A 32-bits signed integer.
|
||||
S32(i32),
|
||||
|
||||
/// A 64-bits signed integer.
|
||||
S64(i64),
|
||||
|
||||
/// A 8-bits unsigned integer.
|
||||
U8(u8),
|
||||
|
||||
/// A 16-bits unsigned integer.
|
||||
U16(u16),
|
||||
|
||||
/// A 32-bits unsigned integer.
|
||||
U32(u32),
|
||||
|
||||
/// A 64-bits unsigned integer.
|
||||
U64(u64),
|
||||
|
||||
/// A 32-bits float.
|
||||
F32(f32),
|
||||
|
||||
/// A 64-bits float.
|
||||
F64(f64),
|
||||
|
||||
/// A string.
|
||||
String(String),
|
||||
|
||||
/// A byte array.
|
||||
Array(Vec<InterfaceValue>),
|
||||
|
||||
//Anyref(?),
|
||||
/// A 32-bits integer (as defined in WebAssembly core).
|
||||
I32(i32),
|
||||
|
||||
/// A 64-bits integer (as defiend in WebAssembly core).
|
||||
I64(i64),
|
||||
|
||||
/// A record.
|
||||
Record(Vec1<InterfaceValue>),
|
||||
}
|
||||
|
||||
impl Default for InterfaceValue {
|
||||
fn default() -> Self {
|
||||
Self::I32(0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a native type supported by WIT.
|
||||
pub trait NativeType {
|
||||
/// The associated interface type that maps to the native type.
|
||||
const INTERFACE_TYPE: InterfaceType;
|
||||
}
|
||||
|
||||
macro_rules! native {
|
||||
($native_type:ty, $variant:ident) => {
|
||||
impl NativeType for $native_type {
|
||||
const INTERFACE_TYPE: InterfaceType = InterfaceType::$variant;
|
||||
}
|
||||
|
||||
impl From<$native_type> for InterfaceValue {
|
||||
fn from(n: $native_type) -> Self {
|
||||
Self::$variant(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&InterfaceValue> for $native_type {
|
||||
type Error = WasmValueNativeCastError;
|
||||
|
||||
fn try_from(w: &InterfaceValue) -> Result<Self, Self::Error> {
|
||||
match w {
|
||||
InterfaceValue::$variant(n) => Ok(n.clone()),
|
||||
_ => Err(WasmValueNativeCastError {
|
||||
from: w.clone(),
|
||||
to: <$native_type>::INTERFACE_TYPE,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
native!(i8, S8);
|
||||
native!(i16, S16);
|
||||
native!(i32, I32);
|
||||
native!(i64, I64);
|
||||
native!(u8, U8);
|
||||
native!(u16, U16);
|
||||
native!(u32, U32);
|
||||
native!(u64, U64);
|
||||
native!(f32, F32);
|
||||
native!(f64, F64);
|
||||
native!(String, String);
|
||||
|
||||
/// Iterates over a vector of `InterfaceValues` but flatten all the
|
||||
/// values. So `I32(1), Record([I32(2), I32(3)]), I32(4)` will be
|
||||
/// iterated like `I32(1), I32(2), I32(3), I32(4)`.
|
||||
pub(crate) struct FlattenInterfaceValueIterator<'a> {
|
||||
iterators: Vec<Iter<'a, InterfaceValue>>,
|
||||
}
|
||||
|
||||
impl<'a> FlattenInterfaceValueIterator<'a> {
|
||||
pub(crate) fn new(values: &'a [InterfaceValue]) -> Self {
|
||||
Self {
|
||||
iterators: vec![values.iter()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for FlattenInterfaceValueIterator<'a> {
|
||||
type Item = &'a InterfaceValue;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.iterators.last_mut()?.next() {
|
||||
// End of the current iterator, go back to the previous
|
||||
// one.
|
||||
None => {
|
||||
self.iterators.pop();
|
||||
self.next()
|
||||
}
|
||||
|
||||
// Recursively iterate over the record.
|
||||
Some(InterfaceValue::Record(fields)) => {
|
||||
self.iterators.push(fields.iter());
|
||||
self.next()
|
||||
}
|
||||
|
||||
// A regular item.
|
||||
e @ Some(_) => e,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
macro_rules! value_to_type {
|
||||
($test_name:ident, $ty:ident, $value:expr) => {
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn $test_name() {
|
||||
assert_eq!(
|
||||
InterfaceType::from(&InterfaceValue::$ty($value)),
|
||||
InterfaceType::$ty
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
value_to_type!(interface_type_from_interface_value__s8, S8, 42);
|
||||
value_to_type!(interface_type_from_interface_value__s16, S16, 42);
|
||||
value_to_type!(interface_type_from_interface_value__s32, S32, 42);
|
||||
value_to_type!(interface_type_from_interface_value__s64, S64, 42);
|
||||
value_to_type!(interface_type_from_interface_value__u8, U8, 42);
|
||||
value_to_type!(interface_type_from_interface_value__u16, U16, 42);
|
||||
value_to_type!(interface_type_from_interface_value__u32, U32, 42);
|
||||
value_to_type!(interface_type_from_interface_value__u64, U64, 42);
|
||||
value_to_type!(interface_type_from_interface_value__f32, F32, 42.);
|
||||
value_to_type!(interface_type_from_interface_value__f64, F64, 42.);
|
||||
value_to_type!(
|
||||
interface_type_from_interface_value__string,
|
||||
String,
|
||||
"foo".to_string()
|
||||
);
|
||||
value_to_type!(interface_type_from_interface_value__i32, I32, 42);
|
||||
value_to_type!(interface_type_from_interface_value__i64, I64, 42);
|
||||
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn interface_type_from_interface_value__record() {
|
||||
assert_eq!(
|
||||
InterfaceType::from(&InterfaceValue::Record(vec1![
|
||||
InterfaceValue::I32(1),
|
||||
InterfaceValue::S8(2)
|
||||
])),
|
||||
InterfaceType::Record(RecordType {
|
||||
fields: vec1![InterfaceType::I32, InterfaceType::S8]
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
InterfaceType::from(&InterfaceValue::Record(vec1![
|
||||
InterfaceValue::I32(1),
|
||||
InterfaceValue::Record(vec1![
|
||||
InterfaceValue::String("a".to_string()),
|
||||
InterfaceValue::F64(42.)
|
||||
]),
|
||||
InterfaceValue::S8(2)
|
||||
])),
|
||||
InterfaceType::Record(RecordType {
|
||||
fields: vec1![
|
||||
InterfaceType::I32,
|
||||
InterfaceType::Record(RecordType {
|
||||
fields: vec1![InterfaceType::String, InterfaceType::F64]
|
||||
}),
|
||||
InterfaceType::S8
|
||||
]
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
25
wasmer-it/Cargo.toml
Normal file
25
wasmer-it/Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "wasmer-interface-types-fl"
|
||||
version = "0.17.20"
|
||||
description = "WebAssembly Interface Types library for Wasmer"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
fluence-it-types = { path = "../crates/it-types", version = "0.1.0" }
|
||||
|
||||
nom = "5.1"
|
||||
wast = "8.0"
|
||||
|
||||
# `serde` is useful only to simplify the users' life. It is not
|
||||
# required by WIT itself, is is used to cross the boundary between the
|
||||
# host and WIT more easily, but it is not used inside Wasm.
|
||||
serde = { version = "1.0", features = ["derive", "rc"], optional = true }
|
||||
serde_json = "1.0"
|
||||
safe-transmute = "0.11.0"
|
||||
log = "0.4.11"
|
||||
|
||||
[features]
|
||||
default = ["serde"]
|
@ -3,7 +3,9 @@
|
||||
|
||||
use crate::{
|
||||
interpreter::Instruction,
|
||||
types::{InterfaceType, RecordType},
|
||||
IValue,
|
||||
IType,
|
||||
IRecordType
|
||||
};
|
||||
|
||||
use serde::Deserialize;
|
||||
@ -28,7 +30,7 @@ pub struct FunctionArg {
|
||||
pub name: String,
|
||||
|
||||
/// A function argument type.
|
||||
pub ty: InterfaceType,
|
||||
pub ty: IType,
|
||||
}
|
||||
|
||||
/// Represents a type.
|
||||
@ -44,7 +46,7 @@ pub enum Type {
|
||||
arguments: Rc<Vec<FunctionArg>>,
|
||||
|
||||
/// Types for the results (`(result …)`).
|
||||
output_types: Rc<Vec<InterfaceType>>,
|
||||
output_types: Rc<Vec<IType>>,
|
||||
},
|
||||
|
||||
/// A record type, like:
|
||||
@ -52,7 +54,7 @@ pub enum Type {
|
||||
/// ```wasm,ignore
|
||||
/// (@interface type (record string i32))
|
||||
/// ```
|
||||
Record(Rc<RecordType>),
|
||||
Record(Rc<IRecordType>),
|
||||
}
|
||||
|
||||
/// Represents an imported function.
|
||||
@ -100,7 +102,7 @@ pub struct Implementation {
|
||||
|
||||
/// Represents the kind of interface.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub(crate) enum InterfaceKind {
|
||||
pub enum InterfaceKind {
|
||||
/// A type.
|
||||
Type,
|
||||
|
@ -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",
|
@ -1,5 +1,11 @@
|
||||
//! Parse the WIT textual representation into an [AST](crate::ast).
|
||||
|
||||
use crate::IType;
|
||||
use crate::ITypeImpl;
|
||||
use crate::RecordFieldType;
|
||||
use crate::RecordFieldTypeImpl;
|
||||
use crate::RecordType;
|
||||
use crate::RecordTypeImpl;
|
||||
use crate::{ast::*, interpreter::Instruction, types::*, vec1::Vec1};
|
||||
use std::rc::Rc;
|
||||
pub use wast::parser::ParseBuffer as Buffer;
|
||||
@ -83,82 +89,82 @@ mod keyword {
|
||||
custom_keyword!(swap2 = "swap2");
|
||||
}
|
||||
|
||||
impl Parse<'_> for InterfaceType {
|
||||
fn parse(parser: Parser<'_>) -> Result<Self> {
|
||||
impl Parse<'_> for ITypeImpl {
|
||||
fn parse(parser: Parser<'_>) -> Result<IType> {
|
||||
let mut lookahead = parser.lookahead1();
|
||||
if lookahead.peek::<keyword::s8>() {
|
||||
parser.parse::<keyword::s8>()?;
|
||||
|
||||
Ok(InterfaceType::S8)
|
||||
Ok(IType::S8)
|
||||
} else if lookahead.peek::<keyword::s16>() {
|
||||
parser.parse::<keyword::s16>()?;
|
||||
|
||||
Ok(InterfaceType::S16)
|
||||
Ok(IType::S16)
|
||||
} else if lookahead.peek::<keyword::s32>() {
|
||||
parser.parse::<keyword::s32>()?;
|
||||
|
||||
Ok(InterfaceType::S32)
|
||||
Ok(IType::S32)
|
||||
} else if lookahead.peek::<keyword::s64>() {
|
||||
parser.parse::<keyword::s64>()?;
|
||||
|
||||
Ok(InterfaceType::S64)
|
||||
Ok(IType::S64)
|
||||
} else if lookahead.peek::<keyword::u8>() {
|
||||
parser.parse::<keyword::u8>()?;
|
||||
|
||||
Ok(InterfaceType::U8)
|
||||
Ok(IType::U8)
|
||||
} else if lookahead.peek::<keyword::u16>() {
|
||||
parser.parse::<keyword::u16>()?;
|
||||
|
||||
Ok(InterfaceType::U16)
|
||||
Ok(IType::U16)
|
||||
} else if lookahead.peek::<keyword::u32>() {
|
||||
parser.parse::<keyword::u32>()?;
|
||||
|
||||
Ok(InterfaceType::U32)
|
||||
Ok(IType::U32)
|
||||
} else if lookahead.peek::<keyword::u64>() {
|
||||
parser.parse::<keyword::u64>()?;
|
||||
|
||||
Ok(InterfaceType::U64)
|
||||
Ok(IType::U64)
|
||||
} else if lookahead.peek::<keyword::f32>() {
|
||||
parser.parse::<keyword::f32>()?;
|
||||
|
||||
Ok(InterfaceType::F32)
|
||||
Ok(IType::F32)
|
||||
} else if lookahead.peek::<keyword::f64>() {
|
||||
parser.parse::<keyword::f64>()?;
|
||||
|
||||
Ok(InterfaceType::F64)
|
||||
Ok(IType::F64)
|
||||
} else if lookahead.peek::<keyword::string>() {
|
||||
parser.parse::<keyword::string>()?;
|
||||
|
||||
Ok(InterfaceType::String)
|
||||
Ok(IType::String)
|
||||
} else if lookahead.peek::<keyword::array>() {
|
||||
parser.parse::<keyword::array>()?;
|
||||
|
||||
let array_type = parser.parens(|p| p.parse())?;
|
||||
|
||||
Ok(InterfaceType::Array(Box::new(array_type)))
|
||||
Ok(IType::Array(Box::new(array_type)))
|
||||
} else if lookahead.peek::<keyword::anyref>() {
|
||||
parser.parse::<keyword::anyref>()?;
|
||||
|
||||
Ok(InterfaceType::Anyref)
|
||||
Ok(IType::Anyref)
|
||||
} else if lookahead.peek::<keyword::i32>() {
|
||||
parser.parse::<keyword::i32>()?;
|
||||
|
||||
Ok(InterfaceType::I32)
|
||||
Ok(IType::I32)
|
||||
} else if lookahead.peek::<keyword::i64>() {
|
||||
parser.parse::<keyword::i64>()?;
|
||||
|
||||
Ok(InterfaceType::I64)
|
||||
Ok(IType::I64)
|
||||
} else if lookahead.peek::<keyword::record>() {
|
||||
parser.parse::<keyword::record>()?;
|
||||
|
||||
Ok(InterfaceType::Record(parser.parse()?))
|
||||
Ok(IType::Record(parser.parse()?))
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse<'_> for RecordType {
|
||||
impl Parse<'_> for RecordTypeImpl {
|
||||
fn parse(parser: Parser<'_>) -> Result<Self> {
|
||||
parser.parse::<keyword::record>()?;
|
||||
|
||||
@ -194,19 +200,24 @@ impl Parse<'_> for RecordType {
|
||||
}
|
||||
|
||||
let ty = parser.parse()?;
|
||||
|
||||
fields.push(RecordFieldType {
|
||||
let record_field_type = RecordFieldType {
|
||||
name: name.trim_end_matches(":").to_string(),
|
||||
ty,
|
||||
});
|
||||
};
|
||||
let record_field_type = RecordFieldTypeImpl(record_field_type);
|
||||
|
||||
fields.push(record_field_type);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(RecordType {
|
||||
let record_type = RecordType {
|
||||
name: record_name,
|
||||
fields: Vec1::new(fields).expect("Record must have at least one field, zero given."),
|
||||
})
|
||||
};
|
||||
let record_type = RecordTypeImpl(record_type);
|
||||
|
||||
Ok(record_type)
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,7 +460,7 @@ impl Parse<'_> for AtInterface {
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum FunctionType {
|
||||
Header(Vec<FunctionArg>),
|
||||
Output(Vec<InterfaceType>),
|
||||
Output(Vec<IType>),
|
||||
}
|
||||
|
||||
impl Parse<'_> for FunctionType {
|
||||
@ -478,7 +489,7 @@ impl Parse<'_> for FunctionType {
|
||||
})?;
|
||||
}
|
||||
|
||||
let arg_type: InterfaceType = parser.parse()?;
|
||||
let arg_type: IType = parser.parse()?;
|
||||
|
||||
arguments.push(FunctionArg {
|
||||
name: arg_name.trim_end_matches(':').to_string(),
|
||||
@ -705,7 +716,7 @@ impl<'a> Parse<'a> for Interfaces<'a> {
|
||||
/// ast::{Adapter, Export, Implementation, Import, Interfaces, Type},
|
||||
/// decoders::wat::{parse, Buffer},
|
||||
/// interpreter::Instruction,
|
||||
/// types::InterfaceType,
|
||||
/// types::IType,
|
||||
/// };
|
||||
///
|
||||
/// let input = Buffer::new(
|
||||
@ -722,8 +733,8 @@ impl<'a> Parse<'a> for Interfaces<'a> {
|
||||
/// .unwrap();
|
||||
/// let output = Interfaces {
|
||||
/// types: vec![Type::Function {
|
||||
/// inputs: vec![InterfaceType::I32],
|
||||
/// outputs: vec![InterfaceType::S8],
|
||||
/// inputs: vec![IType::I32],
|
||||
/// outputs: vec![IType::S8],
|
||||
/// }],
|
||||
/// imports: vec![Import {
|
||||
/// namespace: "ns",
|
||||
@ -779,32 +790,29 @@ mod tests {
|
||||
"record (field string)",
|
||||
];
|
||||
let outputs = vec![
|
||||
InterfaceType::S8,
|
||||
InterfaceType::S16,
|
||||
InterfaceType::S32,
|
||||
InterfaceType::S64,
|
||||
InterfaceType::U8,
|
||||
InterfaceType::U16,
|
||||
InterfaceType::U32,
|
||||
InterfaceType::U64,
|
||||
InterfaceType::F32,
|
||||
InterfaceType::F64,
|
||||
InterfaceType::String,
|
||||
InterfaceType::Anyref,
|
||||
InterfaceType::I32,
|
||||
InterfaceType::I64,
|
||||
InterfaceType::Record(RecordType {
|
||||
fields: vec1![InterfaceType::String],
|
||||
IType::S8,
|
||||
IType::S16,
|
||||
IType::S32,
|
||||
IType::S64,
|
||||
IType::U8,
|
||||
IType::U16,
|
||||
IType::U32,
|
||||
IType::U64,
|
||||
IType::F32,
|
||||
IType::F64,
|
||||
IType::String,
|
||||
IType::Anyref,
|
||||
IType::I32,
|
||||
IType::I64,
|
||||
IType::Record(RecordType {
|
||||
fields: vec1![IType::String],
|
||||
}),
|
||||
];
|
||||
|
||||
assert_eq!(inputs.len(), outputs.len());
|
||||
|
||||
for (input, output) in inputs.iter().zip(outputs.iter()) {
|
||||
assert_eq!(
|
||||
&parser::parse::<InterfaceType>(&buffer(input)).unwrap(),
|
||||
output
|
||||
);
|
||||
assert_eq!(&parser::parse::<IType>(&buffer(input)).unwrap(), output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -817,18 +825,18 @@ mod tests {
|
||||
];
|
||||
let outputs = vec![
|
||||
RecordType {
|
||||
fields: vec1![InterfaceType::String],
|
||||
fields: vec1![IType::String],
|
||||
},
|
||||
RecordType {
|
||||
fields: vec1![InterfaceType::String, InterfaceType::I32],
|
||||
fields: vec1![IType::String, IType::I32],
|
||||
},
|
||||
RecordType {
|
||||
fields: vec1![
|
||||
InterfaceType::String,
|
||||
InterfaceType::Record(RecordType {
|
||||
fields: vec1![InterfaceType::I32, InterfaceType::I32],
|
||||
IType::String,
|
||||
IType::Record(RecordType {
|
||||
fields: vec1![IType::I32, IType::I32],
|
||||
}),
|
||||
InterfaceType::F64,
|
||||
IType::F64,
|
||||
],
|
||||
},
|
||||
];
|
||||
@ -951,7 +959,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_param() {
|
||||
let input = buffer("(param i32 string)");
|
||||
let output = FunctionType::InputTypes(vec![InterfaceType::I32, InterfaceType::String]);
|
||||
let output = FunctionType::InputTypes(vec![IType::I32, IType::String]);
|
||||
|
||||
assert_eq!(parser::parse::<FunctionType>(&input).unwrap(), output);
|
||||
}
|
||||
@ -967,7 +975,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_result() {
|
||||
let input = buffer("(result i32 string)");
|
||||
let output = FunctionType::Output(vec![InterfaceType::I32, InterfaceType::String]);
|
||||
let output = FunctionType::Output(vec![IType::I32, IType::String]);
|
||||
|
||||
assert_eq!(parser::parse::<FunctionType>(&input).unwrap(), output);
|
||||
}
|
||||
@ -976,8 +984,8 @@ mod tests {
|
||||
fn test_type_function() {
|
||||
let input = buffer(r#"(@interface type (func (param i32 i32) (result i32)))"#);
|
||||
let output = Interface::Type(Type::Function {
|
||||
inputs: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::I32],
|
||||
inputs: vec![IType::I32, IType::I32],
|
||||
outputs: vec![IType::I32],
|
||||
});
|
||||
|
||||
assert_eq!(parser::parse::<Interface>(&input).unwrap(), output);
|
||||
@ -987,7 +995,7 @@ mod tests {
|
||||
fn test_type_record() {
|
||||
let input = buffer(r#"(@interface type (record (field string) (field i32)))"#);
|
||||
let output = Interface::Type(Type::Record(RecordType {
|
||||
fields: vec1![InterfaceType::String, InterfaceType::I32],
|
||||
fields: vec1![IType::String, IType::I32],
|
||||
}));
|
||||
|
||||
assert_eq!(parser::parse::<Interface>(&input).unwrap(), output);
|
||||
@ -1064,8 +1072,8 @@ mod tests {
|
||||
);
|
||||
let output = Interfaces {
|
||||
types: vec![Type::Function {
|
||||
inputs: vec![InterfaceType::I32],
|
||||
outputs: vec![InterfaceType::S8],
|
||||
inputs: vec![IType::I32],
|
||||
outputs: vec![IType::S8],
|
||||
}],
|
||||
imports: vec![Import {
|
||||
namespace: "ns",
|
@ -3,6 +3,11 @@
|
||||
use crate::{ast::*, interpreter::Instruction, types::*};
|
||||
use std::io::{self, Write};
|
||||
|
||||
use crate::IType;
|
||||
use crate::ITypeImpl;
|
||||
use crate::RecordFieldTypeImpl;
|
||||
use crate::RecordTypeImpl;
|
||||
|
||||
/// A trait for converting a value to bytes.
|
||||
pub trait ToBytes<W>
|
||||
where
|
||||
@ -106,31 +111,31 @@ where
|
||||
}
|
||||
|
||||
/// Encode an `InterfaceType` into bytes.
|
||||
impl<W> ToBytes<W> for InterfaceType
|
||||
impl<W> ToBytes<W> for ITypeImpl
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
match self {
|
||||
InterfaceType::S8 => 0x00_u8.to_bytes(writer),
|
||||
InterfaceType::S16 => 0x01_u8.to_bytes(writer),
|
||||
InterfaceType::S32 => 0x02_u8.to_bytes(writer),
|
||||
InterfaceType::S64 => 0x03_u8.to_bytes(writer),
|
||||
InterfaceType::U8 => 0x04_u8.to_bytes(writer),
|
||||
InterfaceType::U16 => 0x05_u8.to_bytes(writer),
|
||||
InterfaceType::U32 => 0x06_u8.to_bytes(writer),
|
||||
InterfaceType::U64 => 0x07_u8.to_bytes(writer),
|
||||
InterfaceType::F32 => 0x08_u8.to_bytes(writer),
|
||||
InterfaceType::F64 => 0x09_u8.to_bytes(writer),
|
||||
InterfaceType::String => 0x0a_u8.to_bytes(writer),
|
||||
InterfaceType::Array(ty) => {
|
||||
match self.0 {
|
||||
IType::S8 => 0x00_u8.to_bytes(writer),
|
||||
IType::S16 => 0x01_u8.to_bytes(writer),
|
||||
IType::S32 => 0x02_u8.to_bytes(writer),
|
||||
IType::S64 => 0x03_u8.to_bytes(writer),
|
||||
IType::U8 => 0x04_u8.to_bytes(writer),
|
||||
IType::U16 => 0x05_u8.to_bytes(writer),
|
||||
IType::U32 => 0x06_u8.to_bytes(writer),
|
||||
IType::U64 => 0x07_u8.to_bytes(writer),
|
||||
IType::F32 => 0x08_u8.to_bytes(writer),
|
||||
IType::F64 => 0x09_u8.to_bytes(writer),
|
||||
IType::String => 0x0a_u8.to_bytes(writer),
|
||||
IType::Array(ty) => {
|
||||
0x36_u8.to_bytes(writer)?;
|
||||
ty.to_bytes(writer)
|
||||
}
|
||||
InterfaceType::Anyref => 0x0b_u8.to_bytes(writer),
|
||||
InterfaceType::I32 => 0x0c_u8.to_bytes(writer),
|
||||
InterfaceType::I64 => 0x0d_u8.to_bytes(writer),
|
||||
InterfaceType::Record(record_id) => {
|
||||
IType::Anyref => 0x0b_u8.to_bytes(writer),
|
||||
IType::I32 => 0x0c_u8.to_bytes(writer),
|
||||
IType::I64 => 0x0d_u8.to_bytes(writer),
|
||||
IType::Record(record_id) => {
|
||||
0x0e_u8.to_bytes(writer)?;
|
||||
record_id.to_bytes(writer)
|
||||
}
|
||||
@ -139,24 +144,26 @@ where
|
||||
}
|
||||
|
||||
/// Encode a `RecordType` into bytes.
|
||||
impl<W> ToBytes<W> for RecordFieldType
|
||||
impl<W> ToBytes<W> for RecordFieldTypeImpl
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
self.name.as_str().to_bytes(writer)?;
|
||||
self.ty.to_bytes(writer)
|
||||
let record_field_type = &self.0;
|
||||
record_field_type.name.as_str().to_bytes(writer)?;
|
||||
record_field_type.ty.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a `RecordType` into bytes.
|
||||
impl<W> ToBytes<W> for RecordType
|
||||
impl<W> ToBytes<W> for RecordTypeImpl
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
self.name.as_str().to_bytes(writer)?;
|
||||
self.fields.to_bytes(writer)
|
||||
let record_type = &self.0;
|
||||
record_type.name.as_str().to_bytes(writer)?;
|
||||
record_type.fields.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
@ -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());
|
||||
}
|
@ -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);
|
@ -1,16 +1,13 @@
|
||||
//! Provides a deserializer from WIT values to Rust value.
|
||||
|
||||
use crate::{
|
||||
types::InterfaceType,
|
||||
values::{FlattenInterfaceValueIterator, InterfaceValue},
|
||||
};
|
||||
use crate::{values::FlattenIValueIterator, IType, IValue};
|
||||
use serde::{de, Deserialize};
|
||||
use std::{
|
||||
fmt::{self, Display},
|
||||
iter::Peekable,
|
||||
};
|
||||
|
||||
/// Deserialize a set of `InterfaceValue`s to a type `T` that
|
||||
/// Deserialize a set of `IValue`s to a type `T` that
|
||||
/// implements the `Deserialize` trait.
|
||||
///
|
||||
/// This is not a requirement to use WIT, but Serde provides an even
|
||||
@ -21,7 +18,7 @@ use std::{
|
||||
///
|
||||
/// ```rust
|
||||
/// use wasmer_interface_types::{
|
||||
/// values::{InterfaceValue, from_interface_values},
|
||||
/// values::{IValue, from_interface_values},
|
||||
/// vec1::Vec1,
|
||||
/// };
|
||||
/// use serde::Deserialize;
|
||||
@ -36,10 +33,10 @@ use std::{
|
||||
/// y: f32,
|
||||
/// };
|
||||
///
|
||||
/// let values = vec![InterfaceValue::Record(Vec1::new(vec![
|
||||
/// InterfaceValue::String("abc".to_string()),
|
||||
/// InterfaceValue::Record(Vec1::new(vec![InterfaceValue::I32(1), InterfaceValue::I64(2)]).unwrap()),
|
||||
/// InterfaceValue::F32(3.),
|
||||
/// let values = vec![IValue::Record(Vec1::new(vec![
|
||||
/// IValue::String("abc".to_string()),
|
||||
/// IValue::Record(Vec1::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()),
|
||||
/// IValue::F32(3.),
|
||||
/// ]).unwrap())];
|
||||
/// let t = from_interface_values::<T>(&values).unwrap();
|
||||
///
|
||||
@ -52,7 +49,7 @@ use std::{
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
pub fn from_interface_values<'a, T>(values: &'a [InterfaceValue]) -> Result<T, DeserializeError>
|
||||
pub fn from_interface_values<'a, T>(values: &'a [IValue]) -> Result<T, DeserializeError>
|
||||
where
|
||||
T: Deserialize<'a>,
|
||||
{
|
||||
@ -66,15 +63,15 @@ where
|
||||
}
|
||||
|
||||
/// The deserializer. The iterator iterates over `InterfaceValue`s,
|
||||
/// all flatten, see `FlattenInterfaceValueIterator`.
|
||||
/// all flatten, see `FlattenIValueIterator`.
|
||||
struct Deserializer<'de> {
|
||||
iterator: Peekable<FlattenInterfaceValueIterator<'de>>,
|
||||
iterator: Peekable<FlattenIValueIterator<'de>>,
|
||||
}
|
||||
|
||||
impl<'de> Deserializer<'de> {
|
||||
pub fn new(input: &'de [InterfaceValue]) -> Deserializer<'de> {
|
||||
Deserializer {
|
||||
iterator: FlattenInterfaceValueIterator::new(input).peekable(),
|
||||
iterator: FlattenIValueIterator::new(input).peekable(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,14 +80,14 @@ macro_rules! next {
|
||||
($method_name:ident, $variant:ident, $type:ty) => {
|
||||
fn $method_name(&mut self) -> Result<$type, DeserializeError> {
|
||||
match self.iterator.peek() {
|
||||
Some(InterfaceValue::$variant(value)) => {
|
||||
Some(IValue::$variant(value)) => {
|
||||
self.iterator.next();
|
||||
|
||||
Ok(*value)
|
||||
}
|
||||
|
||||
Some(wrong_value) => Err(DeserializeError::TypeMismatch {
|
||||
expected_type: InterfaceType::$variant,
|
||||
expected_type: IType::$variant,
|
||||
received_value: (*wrong_value).clone(),
|
||||
}),
|
||||
|
||||
@ -114,14 +111,14 @@ impl<'de> Deserializer<'de> {
|
||||
|
||||
fn next_string(&mut self) -> Result<&'de str, DeserializeError> {
|
||||
match self.iterator.peek() {
|
||||
Some(InterfaceValue::String(v)) => {
|
||||
Some(IValue::String(v)) => {
|
||||
self.iterator.next();
|
||||
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
Some(wrong_value) => Err(DeserializeError::TypeMismatch {
|
||||
expected_type: InterfaceType::String,
|
||||
expected_type: IType::String,
|
||||
received_value: (*wrong_value).clone(),
|
||||
}),
|
||||
|
||||
@ -131,7 +128,7 @@ impl<'de> Deserializer<'de> {
|
||||
|
||||
fn next_array(&mut self) -> Result<&'de [u8], DeserializeError> {
|
||||
match self.iterator.peek() {
|
||||
Some(InterfaceValue::Array(_)) => {
|
||||
Some(IValue::Array(_)) => {
|
||||
self.iterator.next();
|
||||
|
||||
// Ok(v)
|
||||
@ -141,7 +138,7 @@ impl<'de> Deserializer<'de> {
|
||||
|
||||
Some(wrong_value) => Err(DeserializeError::TypeMismatch {
|
||||
// TODO: change default
|
||||
expected_type: InterfaceType::Array(Box::new(InterfaceType::S8)),
|
||||
expected_type: IType::Array(Box::new(IType::S8)),
|
||||
received_value: (*wrong_value).clone(),
|
||||
}),
|
||||
|
||||
@ -165,10 +162,10 @@ pub enum DeserializeError {
|
||||
/// The current value hasn't the expected type.
|
||||
TypeMismatch {
|
||||
/// The expected type.
|
||||
expected_type: InterfaceType,
|
||||
expected_type: IType,
|
||||
|
||||
/// The received type.
|
||||
received_value: InterfaceValue,
|
||||
received_value: IValue,
|
||||
},
|
||||
|
||||
/// Arbitrary message.
|
||||
@ -209,21 +206,21 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
match self.iterator.peek() {
|
||||
Some(InterfaceValue::S8(_)) => self.deserialize_i8(visitor),
|
||||
Some(InterfaceValue::S16(_)) => self.deserialize_i16(visitor),
|
||||
Some(InterfaceValue::S32(_)) => self.deserialize_i32(visitor),
|
||||
Some(InterfaceValue::S64(_)) => self.deserialize_i64(visitor),
|
||||
Some(InterfaceValue::U8(_)) => self.deserialize_u8(visitor),
|
||||
Some(InterfaceValue::U16(_)) => self.deserialize_u16(visitor),
|
||||
Some(InterfaceValue::U32(_)) => self.deserialize_u32(visitor),
|
||||
Some(InterfaceValue::U64(_)) => self.deserialize_u64(visitor),
|
||||
Some(InterfaceValue::F32(_)) => self.deserialize_f32(visitor),
|
||||
Some(InterfaceValue::F64(_)) => self.deserialize_f64(visitor),
|
||||
Some(InterfaceValue::String(_)) => self.deserialize_string(visitor),
|
||||
Some(InterfaceValue::Array(_)) => self.deserialize_bytes(visitor),
|
||||
Some(InterfaceValue::I32(_)) => self.deserialize_i32(visitor),
|
||||
Some(InterfaceValue::I64(_)) => self.deserialize_i64(visitor),
|
||||
Some(InterfaceValue::Record(..)) => unreachable!("Records should have been flattened."), // already flattened
|
||||
Some(IValue::S8(_)) => self.deserialize_i8(visitor),
|
||||
Some(IValue::S16(_)) => self.deserialize_i16(visitor),
|
||||
Some(IValue::S32(_)) => self.deserialize_i32(visitor),
|
||||
Some(IValue::S64(_)) => self.deserialize_i64(visitor),
|
||||
Some(IValue::U8(_)) => self.deserialize_u8(visitor),
|
||||
Some(IValue::U16(_)) => self.deserialize_u16(visitor),
|
||||
Some(IValue::U32(_)) => self.deserialize_u32(visitor),
|
||||
Some(IValue::U64(_)) => self.deserialize_u64(visitor),
|
||||
Some(IValue::F32(_)) => self.deserialize_f32(visitor),
|
||||
Some(IValue::F64(_)) => self.deserialize_f64(visitor),
|
||||
Some(IValue::String(_)) => self.deserialize_string(visitor),
|
||||
Some(IValue::Array(_)) => self.deserialize_bytes(visitor),
|
||||
Some(IValue::I32(_)) => self.deserialize_i32(visitor),
|
||||
Some(IValue::I64(_)) => self.deserialize_i64(visitor),
|
||||
Some(IValue::Record(..)) => unreachable!("Records should have been flattened."), // already flattened
|
||||
None => Err(DeserializeError::InputEmpty),
|
||||
}
|
||||
}
|
||||
@ -253,7 +250,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
// Both `InterfaceValue::S32` and `InterfaceValue::I32`
|
||||
// Both `IValue::S32` and `IValue::I32`
|
||||
// represent `i32`.
|
||||
visitor.visit_i32(self.next_s32().or_else(|_| self.next_i32())?)
|
||||
}
|
||||
@ -262,7 +259,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
// Both `InterfaceValue::S64` and `InterfaceValue::I64`
|
||||
// Both `IValue::S64` and `IValue::I64`
|
||||
// represent `i64`.
|
||||
visitor.visit_i64(self.next_s64().or_else(|_| self.next_i64())?)
|
||||
}
|
||||
@ -489,7 +486,7 @@ mod tests {
|
||||
#[test]
|
||||
#[allow(non_snake_case)]
|
||||
fn $test_name() {
|
||||
let input = vec![InterfaceValue::$variant($value)];
|
||||
let input = vec![IValue::$variant($value)];
|
||||
let output: $ty = $value;
|
||||
|
||||
assert_eq!(from_interface_values::<$ty>(&input).unwrap(), output);
|
||||
@ -518,7 +515,7 @@ mod tests {
|
||||
#[allow(non_snake_case)]
|
||||
fn test_deserialize_value__str() {
|
||||
let foo = "foo".to_string();
|
||||
let values = vec![InterfaceValue::String(foo)];
|
||||
let values = vec![IValue::String(foo)];
|
||||
let input: &str = from_interface_values(&values).unwrap();
|
||||
let output: &str = "foo";
|
||||
|
||||
@ -534,7 +531,7 @@ mod tests {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
struct S(i8);
|
||||
|
||||
let input = vec![InterfaceValue::Record(vec1![InterfaceValue::S8(42)])];
|
||||
let input = vec![IValue::Record(vec1![IValue::S8(42)])];
|
||||
let output = S(42);
|
||||
|
||||
assert_eq!(from_interface_values::<S>(&input).unwrap(), output);
|
||||
@ -546,10 +543,7 @@ mod tests {
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
struct S(i8, f32);
|
||||
|
||||
let input = vec![InterfaceValue::Record(vec1![
|
||||
InterfaceValue::S8(7),
|
||||
InterfaceValue::F32(42.),
|
||||
])];
|
||||
let input = vec![IValue::Record(vec1![IValue::S8(7), IValue::F32(42.),])];
|
||||
let output = S(7, 42.);
|
||||
|
||||
assert_eq!(from_interface_values::<S>(&input).unwrap(), output);
|
||||
@ -564,10 +558,7 @@ mod tests {
|
||||
y: f32,
|
||||
}
|
||||
|
||||
let input = vec![InterfaceValue::Record(vec1![
|
||||
InterfaceValue::S8(7),
|
||||
InterfaceValue::F32(42.),
|
||||
])];
|
||||
let input = vec![IValue::Record(vec1![IValue::S8(7), IValue::F32(42.),])];
|
||||
let output = S { x: 7, y: 42. };
|
||||
|
||||
assert_eq!(from_interface_values::<S>(&input).unwrap(), output);
|
||||
@ -589,17 +580,9 @@ mod tests {
|
||||
p2: Point,
|
||||
}
|
||||
|
||||
let input = vec![InterfaceValue::Record(vec1![
|
||||
InterfaceValue::Record(vec1![
|
||||
InterfaceValue::I32(1),
|
||||
InterfaceValue::I32(2),
|
||||
InterfaceValue::I32(3),
|
||||
]),
|
||||
InterfaceValue::Record(vec1![
|
||||
InterfaceValue::I32(4),
|
||||
InterfaceValue::I32(5),
|
||||
InterfaceValue::I32(6),
|
||||
]),
|
||||
let input = vec![IValue::Record(vec1![
|
||||
IValue::Record(vec1![IValue::I32(1), IValue::I32(2), IValue::I32(3),]),
|
||||
IValue::Record(vec1![IValue::I32(4), IValue::I32(5), IValue::I32(6),]),
|
||||
])];
|
||||
let output = Line {
|
||||
p1: Point { x: 1, y: 2, z: 3 },
|
@ -1,11 +1,13 @@
|
||||
//! Provides a serializer from Rust value to WIT values.
|
||||
|
||||
use crate::{values::InterfaceValue, vec1::Vec1};
|
||||
use crate::IValue;
|
||||
use crate::IValueImpl;
|
||||
use crate::Vec1;
|
||||
use serde::{ser, Serialize};
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
/// Serialize a type `T` that implements the `Serialize` trait to an
|
||||
/// `InterfaceValue`.
|
||||
/// `IValue`.
|
||||
///
|
||||
/// This is not a requirement to use WIT, but Serde provides an even
|
||||
/// nicer API to the user to send its complex types to WIT.
|
||||
@ -14,7 +16,7 @@ use std::fmt::{self, Display};
|
||||
///
|
||||
/// ```rust
|
||||
/// use wasmer_interface_types::{
|
||||
/// values::{InterfaceValue, to_interface_value},
|
||||
/// values::{IValue, to_interface_value},
|
||||
/// vec1::Vec1,
|
||||
/// };
|
||||
/// use serde::Serialize;
|
||||
@ -37,18 +39,19 @@ use std::fmt::{self, Display};
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// to_interface_value(&input).unwrap(),
|
||||
/// InterfaceValue::Record(Vec1::new(vec![
|
||||
/// InterfaceValue::String("abc".to_string()),
|
||||
/// InterfaceValue::Record(Vec1::new(vec![InterfaceValue::I32(1), InterfaceValue::I64(2)]).unwrap()),
|
||||
/// InterfaceValue::F32(3.),
|
||||
/// IValue::Record(Vec1::new(vec![
|
||||
/// IValue::String("abc".to_string()),
|
||||
/// IValue::Record(Vec1::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()),
|
||||
/// IValue::F32(3.),
|
||||
/// ]).unwrap()),
|
||||
/// );
|
||||
/// ```
|
||||
pub fn to_interface_value<T>(value: &T) -> Result<InterfaceValue, SerializeError>
|
||||
pub fn to_interface_value<T>(value: &T) -> Result<IValue, SerializeError>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let mut serializer = Serializer::new();
|
||||
let value = ValueImpl(value);
|
||||
value.serialize(&mut serializer)?;
|
||||
|
||||
if serializer.values.len() != 1 {
|
||||
@ -61,14 +64,14 @@ where
|
||||
} else {
|
||||
let first_value = first_values.pop().unwrap(); // this `unwrap` is safe because we are sure the length is 1.
|
||||
|
||||
Ok(first_value)
|
||||
Ok(first_value.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The serializer.
|
||||
struct Serializer {
|
||||
values: Vec<Vec<InterfaceValue>>,
|
||||
values: Vec<Vec<IValueImpl>>,
|
||||
}
|
||||
|
||||
impl Serializer {
|
||||
@ -78,7 +81,7 @@ impl Serializer {
|
||||
}
|
||||
}
|
||||
|
||||
fn last(&mut self) -> &mut Vec<InterfaceValue> {
|
||||
fn last(&mut self) -> &mut Vec<IValueImpl> {
|
||||
self.values.last_mut().unwrap()
|
||||
}
|
||||
|
||||
@ -86,7 +89,7 @@ impl Serializer {
|
||||
self.values.push(Vec::with_capacity(capacity));
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Result<Vec<InterfaceValue>, SerializeError> {
|
||||
fn pop(&mut self) -> Result<Vec<IValueImpl>, SerializeError> {
|
||||
// The first `vec` contains the final result. It is forbidden
|
||||
// to `pop` it as is.
|
||||
if self.values.len() < 2 {
|
||||
@ -361,9 +364,10 @@ impl<'a> ser::SerializeSeq for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
let record = InterfaceValue::Record(
|
||||
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
|
||||
);
|
||||
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
|
||||
|
||||
let record = IValue::Array(values);
|
||||
let record = IValueImpl(record);
|
||||
self.last().push(record);
|
||||
|
||||
Ok(())
|
||||
@ -398,9 +402,11 @@ impl<'a> ser::SerializeTupleStruct for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
let record = InterfaceValue::Record(
|
||||
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
|
||||
);
|
||||
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
|
||||
|
||||
let record =
|
||||
IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?);
|
||||
let record = ValueImpl(record);
|
||||
self.last().push(record);
|
||||
|
||||
Ok(())
|
||||
@ -442,9 +448,11 @@ impl<'a> ser::SerializeMap for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
let record = InterfaceValue::Record(
|
||||
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
|
||||
);
|
||||
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
|
||||
|
||||
let record =
|
||||
IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?);
|
||||
let record = ValueImpl(record);
|
||||
self.last().push(record);
|
||||
|
||||
Ok(())
|
||||
@ -463,9 +471,11 @@ impl<'a> ser::SerializeStruct for &'a mut Serializer {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
let record = InterfaceValue::Record(
|
||||
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
|
||||
);
|
||||
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
|
||||
|
||||
let record =
|
||||
IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?);
|
||||
let record = ValueImpl(record);
|
||||
self.last().push(record);
|
||||
|
||||
Ok(())
|
||||
@ -502,7 +512,7 @@ mod tests {
|
||||
#[allow(non_snake_case)]
|
||||
fn $test_name() {
|
||||
let input: $ty = $value;
|
||||
let output = InterfaceValue::$variant($value);
|
||||
let output = IValue::$variant($value);
|
||||
|
||||
assert_eq!(to_interface_value(&input).unwrap(), output);
|
||||
}
|
||||
@ -533,7 +543,7 @@ mod tests {
|
||||
struct S(i8);
|
||||
|
||||
let input = S(42);
|
||||
let output = InterfaceValue::S8(42);
|
||||
let output = IValue::S8(42);
|
||||
|
||||
assert_eq!(to_interface_value(&input).unwrap(), output);
|
||||
}
|
||||
@ -545,7 +555,7 @@ mod tests {
|
||||
struct S(i8, f32);
|
||||
|
||||
let input = S(7, 42.);
|
||||
let output = InterfaceValue::Record(vec1![InterfaceValue::S8(7), InterfaceValue::F32(42.)]);
|
||||
let output = IValue::Record(vec1![IValue::S8(7), IValue::F32(42.)]);
|
||||
|
||||
assert_eq!(to_interface_value(&input).unwrap(), output);
|
||||
}
|
||||
@ -560,7 +570,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let input = S { x: 7, y: 42. };
|
||||
let output = InterfaceValue::Record(vec1![InterfaceValue::S8(7), InterfaceValue::F32(42.)]);
|
||||
let output = IValue::Record(vec1![IValue::S8(7), IValue::F32(42.)]);
|
||||
|
||||
assert_eq!(to_interface_value(&input).unwrap(), output);
|
||||
}
|
||||
@ -585,17 +595,9 @@ mod tests {
|
||||
p1: Point { x: 1, y: 2, z: 3 },
|
||||
p2: Point { x: 4, y: 5, z: 6 },
|
||||
};
|
||||
let output = InterfaceValue::Record(vec1![
|
||||
InterfaceValue::Record(vec1![
|
||||
InterfaceValue::I32(1),
|
||||
InterfaceValue::I32(2),
|
||||
InterfaceValue::I32(3),
|
||||
]),
|
||||
InterfaceValue::Record(vec1![
|
||||
InterfaceValue::I32(4),
|
||||
InterfaceValue::I32(5),
|
||||
InterfaceValue::I32(6),
|
||||
]),
|
||||
let output = IValue::Record(vec1![
|
||||
IValue::Record(vec1![IValue::I32(1), IValue::I32(2), IValue::I32(3),]),
|
||||
IValue::Record(vec1![IValue::I32(4), IValue::I32(5), IValue::I32(6),]),
|
||||
]);
|
||||
|
||||
assert_eq!(to_interface_value(&input).unwrap(), output);
|
94
wasmer-it/src/values.rs
Normal file
94
wasmer-it/src/values.rs
Normal file
@ -0,0 +1,94 @@
|
||||
use crate::IType;
|
||||
use crate::IValue;
|
||||
use crate::IValueImpl;
|
||||
use crate::{errors::WasmValueNativeCastError, types::IType, vec1::Vec1};
|
||||
use std::{convert::TryFrom, slice::Iter};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
pub use crate::serde::{de::from_interface_values, ser::to_interface_value};
|
||||
|
||||
/// Represents a native type supported by WIT.
|
||||
pub trait NativeType {
|
||||
/// The associated interface type that maps to the native type.
|
||||
const INTERFACE_TYPE: IType;
|
||||
}
|
||||
|
||||
macro_rules! native {
|
||||
($native_type:ty, $variant:ident) => {
|
||||
impl NativeType for $native_type {
|
||||
const INTERFACE_TYPE: IType = IType::$variant;
|
||||
}
|
||||
|
||||
impl From<$native_type> for IValueImpl {
|
||||
fn from(n: $native_type) -> Self {
|
||||
let ivalue = IValue::$variant(n);
|
||||
Self(ivalue)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&IValueImpl> for $native_type {
|
||||
type Error = WasmValueNativeCastError;
|
||||
|
||||
fn try_from(w: &IValue) -> Result<Self, Self::Error> {
|
||||
match w {
|
||||
IValue::$variant(n) => Ok(n.clone()),
|
||||
_ => Err(WasmValueNativeCastError {
|
||||
from: w.clone(),
|
||||
to: <$native_type>::INTERFACE_TYPE,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
native!(i8, S8);
|
||||
native!(i16, S16);
|
||||
native!(i32, I32);
|
||||
native!(i64, I64);
|
||||
native!(u8, U8);
|
||||
native!(u16, U16);
|
||||
native!(u32, U32);
|
||||
native!(u64, U64);
|
||||
native!(f32, F32);
|
||||
native!(f64, F64);
|
||||
native!(String, String);
|
||||
|
||||
/// Iterates over a vector of `IValues` but flatten all the
|
||||
/// values. So `I32(1), Record([I32(2), I32(3)]), I32(4)` will be
|
||||
/// iterated like `I32(1), I32(2), I32(3), I32(4)`.
|
||||
pub(crate) struct FlattenIValueIterator<'a> {
|
||||
iterators: Vec<Iter<'a, IValue>>,
|
||||
}
|
||||
|
||||
impl<'a> FlattenIValueIterator<'a> {
|
||||
pub(crate) fn new(values: &'a [IValue]) -> Self {
|
||||
Self {
|
||||
iterators: vec![values.iter()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for FlattenIValueIterator<'a> {
|
||||
type Item = &'a IValue;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.iterators.last_mut()?.next() {
|
||||
// End of the current iterator, go back to the previous
|
||||
// one.
|
||||
None => {
|
||||
self.iterators.pop();
|
||||
self.next()
|
||||
}
|
||||
|
||||
// Recursively iterate over the record.
|
||||
Some(IValue::Record(fields)) => {
|
||||
self.iterators.push(fields.iter());
|
||||
self.next()
|
||||
}
|
||||
|
||||
// A regular item.
|
||||
e @ Some(_) => e,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user