Skip to content

Commit

Permalink
feat(interface-types) InterfaceValue::Record now takes a Vec1.
Browse files Browse the repository at this point in the history
It matches the definition of `InterfaceType::Record`.
  • Loading branch information
Hywan committed Apr 9, 2020
1 parent 700c290 commit 4c2fb95
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 54 deletions.
30 changes: 17 additions & 13 deletions lib/interface-types/src/interpreter/instructions/records.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
},
types::{InterfaceType, RecordType},
values::{FlattenInterfaceValueIterator, InterfaceValue},
vec1::Vec1,
};
use std::collections::VecDeque;

Expand Down Expand Up @@ -56,7 +57,10 @@ fn record_lift_(
}
}

Ok(InterfaceValue::Record(values.into_iter().collect()))
Ok(InterfaceValue::Record(
Vec1::new(values.into_iter().collect())
.expect("Record must have at least one field, zero given"), // normally unreachable because of the type-checking
))
}

executable_instruction!(
Expand Down Expand Up @@ -110,7 +114,7 @@ executable_instruction!(
};

match runtime.stack.pop1() {
Some(InterfaceValue::Record(record_values)) if record_type == &(&record_values).into() => {
Some(InterfaceValue::Record(record_values)) if record_type == &(&*record_values).into() => {
let values = FlattenInterfaceValueIterator::new(&record_values);

for value in values {
Expand Down Expand Up @@ -157,9 +161,9 @@ mod tests {
InterfaceValue::I64(3),
],
instance: Instance::new(),
stack: [InterfaceValue::Record(vec![
stack: [InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::String("Hello".to_string()),
InterfaceValue::F32(2.),
]),
Expand Down Expand Up @@ -255,7 +259,7 @@ mod tests {

instance
},
stack: [InterfaceValue::Record(vec![
stack: [InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::I32(2),
])],
Expand Down Expand Up @@ -298,9 +302,9 @@ mod tests {
Instruction::RecordLower { type_index: 0 },
],
invocation_inputs: [
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::String("Hello".to_string()),
InterfaceValue::F32(2.),
]),
Expand All @@ -324,9 +328,9 @@ mod tests {
Instruction::RecordLift { type_index: 0 },
],
invocation_inputs: [
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::String("Hello".to_string()),
InterfaceValue::F32(2.),
]),
Expand All @@ -335,9 +339,9 @@ mod tests {
],
instance: Instance::new(),
stack: [
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::String("Hello".to_string()),
InterfaceValue::F32(2.),
]),
Expand Down Expand Up @@ -366,9 +370,9 @@ mod tests {
Instruction::RecordLower { type_index: 0 },
],
invocation_inputs: [
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::String("Hello".to_string()),
]),
InterfaceValue::I64(3),
Expand Down
15 changes: 9 additions & 6 deletions lib/interface-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
//! This crate contains an implementation of [WebAssembly Interface
//! Types][wit] (abbreviated WIT). It is composed of 4 parts:
//! Types][wit] (abbreviated WIT). It is composed of 5 parts:
//!
//! 1. [AST]: To represent the WIT language as a tree
//! 1. [Types] and [Values]: To represent the WIT types and values
//! representations,
//! 2. [AST]: To represent the WIT language as a tree
//! (which is not really abstract). This is the central
//! representation of the language.
//! 2. [Decoders](decoders): To read the [AST] from a particular data
//! 3. [Decoders](decoders): To read the [AST] from a particular data
//! representation; for instance, [`decoders::binary`] reads the
//! [AST] from a binary.
//! 3. [Encoders](encoders): To write the [AST](ast) into a particular
//! 4. [Encoders](encoders): To write the [AST](ast) into a particular
//! format; for instance, [`encoders::wat`] writes the [AST] into a
//! string representing WIT with its textual format.
//! 4. [Interpreter](interpreter): WIT defines a concept called
//! 5. [Interpreter](interpreter): WIT defines a concept called
//! Adapters. An adapter contains a set of [instructions]. So, in
//! more details, this module contains:
//! * [A very light and generic stack
Expand All @@ -30,8 +32,9 @@
//! this is the part a runtime should take a look to use the
//! `wasmer-interface-types` crate—.
//!
//!
//! [wit]: https://github.com/WebAssembly/interface-types
//! [Types]: types
//! [Values]: values
//! [AST]: ast
//! [instructions]: interpreter::Instruction
Expand Down
4 changes: 3 additions & 1 deletion lib/interface-types/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Collection of helpful macros.
/// This macro creates a `Vec1` by checking at compile-time that its
/// invariant holds.
#[allow(unused)]
#[macro_export]
macro_rules! vec1 {
($item:expr; 0) => {
compile_error!("Cannot create an empty `Vec1`, it violates its invariant.")
Expand Down
24 changes: 12 additions & 12 deletions lib/interface-types/src/serde/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ use std::{
/// # Example
///
/// ```rust
/// use wasmer_interface_types::values::{
/// InterfaceValue,
/// from_interface_values,
/// use wasmer_interface_types::{
/// values::{InterfaceValue, from_interface_values},
/// vec1::Vec1,
/// };
/// use serde::Deserialize;
///
Expand All @@ -36,11 +36,11 @@ use std::{
/// y: f32,
/// };
///
/// let values = vec![InterfaceValue::Record(vec![
/// let values = vec![InterfaceValue::Record(Vec1::new(vec![
/// InterfaceValue::String("abc".to_string()),
/// InterfaceValue::Record(vec![InterfaceValue::I32(1), InterfaceValue::I64(2)]),
/// InterfaceValue::Record(Vec1::new(vec![InterfaceValue::I32(1), InterfaceValue::I64(2)]).unwrap()),
/// InterfaceValue::F32(3.),
/// ])];
/// ]).unwrap())];
/// let t = from_interface_values::<T>(&values).unwrap();
///
/// assert_eq!(
Expand Down Expand Up @@ -513,7 +513,7 @@ mod tests {
#[derive(Deserialize, Debug, PartialEq)]
struct S(i8);

let input = vec![InterfaceValue::Record(vec![InterfaceValue::S8(42)])];
let input = vec![InterfaceValue::Record(vec1![InterfaceValue::S8(42)])];
let output = S(42);

assert_eq!(from_interface_values::<S>(&input).unwrap(), output);
Expand All @@ -525,7 +525,7 @@ mod tests {
#[derive(Deserialize, Debug, PartialEq)]
struct S(i8, f32);

let input = vec![InterfaceValue::Record(vec![
let input = vec![InterfaceValue::Record(vec1![
InterfaceValue::S8(7),
InterfaceValue::F32(42.),
])];
Expand All @@ -543,7 +543,7 @@ mod tests {
y: f32,
}

let input = vec![InterfaceValue::Record(vec![
let input = vec![InterfaceValue::Record(vec1![
InterfaceValue::S8(7),
InterfaceValue::F32(42.),
])];
Expand All @@ -568,13 +568,13 @@ mod tests {
p2: Point,
}

let input = vec![InterfaceValue::Record(vec![
InterfaceValue::Record(vec![
let input = vec![InterfaceValue::Record(vec1![
InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::I32(2),
InterfaceValue::I32(3),
]),
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::I32(4),
InterfaceValue::I32(5),
InterfaceValue::I32(6),
Expand Down
39 changes: 25 additions & 14 deletions lib/interface-types/src/serde/ser.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Provides a serializer from Rust value to WIT values.
use crate::values::InterfaceValue;
use crate::{values::InterfaceValue, vec1::Vec1};
use serde::{ser, Serialize};
use std::fmt::{self, Display};

Expand All @@ -13,9 +13,9 @@ use std::fmt::{self, Display};
/// # Example
///
/// ```rust
/// use wasmer_interface_types::values::{
/// InterfaceValue,
/// to_interface_value,
/// use wasmer_interface_types::{
/// values::{InterfaceValue, to_interface_value},
/// vec1::Vec1,
/// };
/// use serde::Serialize;
///
Expand All @@ -37,11 +37,11 @@ use std::fmt::{self, Display};
///
/// assert_eq!(
/// to_interface_value(&input).unwrap(),
/// InterfaceValue::Record(vec![
/// InterfaceValue::Record(Vec1::new(vec![
/// InterfaceValue::String("abc".to_string()),
/// InterfaceValue::Record(vec![InterfaceValue::I32(1), InterfaceValue::I64(2)]),
/// InterfaceValue::Record(Vec1::new(vec![InterfaceValue::I32(1), InterfaceValue::I64(2)]).unwrap()),
/// InterfaceValue::F32(3.),
/// ]),
/// ]).unwrap()),
/// );
/// ```
pub fn to_interface_value<T>(value: &T) -> Result<InterfaceValue, SerializeError>
Expand Down Expand Up @@ -107,6 +107,9 @@ pub enum SerializeError {
/// serialization.
InternalValuesCorrupted,

/// A record must contain at least one field.
RecordNeedsAtLeastOneField,

/// Arbitrary message.
Message(String),
}
Expand All @@ -128,6 +131,10 @@ impl Display for SerializeError {
formatter,
"the internal values have been corrutped during the serialization"
),
Self::RecordNeedsAtLeastOneField => write!(
formatter,
"a record must contain at least one field, zero given"
),
Self::Message(ref msg) => write!(formatter, "{}", msg),
}
}
Expand Down Expand Up @@ -374,7 +381,9 @@ impl<'a> ser::SerializeTupleStruct for &'a mut Serializer {
}

fn end(self) -> Result<Self::Ok, Self::Error> {
let record = InterfaceValue::Record(self.pop()?);
let record = InterfaceValue::Record(
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
);
self.last().push(record);

Ok(())
Expand Down Expand Up @@ -432,7 +441,9 @@ impl<'a> ser::SerializeStruct for &'a mut Serializer {
}

fn end(self) -> Result<Self::Ok, Self::Error> {
let record = InterfaceValue::Record(self.pop()?);
let record = InterfaceValue::Record(
Vec1::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?,
);
self.last().push(record);

Ok(())
Expand Down Expand Up @@ -512,7 +523,7 @@ mod tests {
struct S(i8, f32);

let input = S(7, 42.);
let output = InterfaceValue::Record(vec![InterfaceValue::S8(7), InterfaceValue::F32(42.)]);
let output = InterfaceValue::Record(vec1![InterfaceValue::S8(7), InterfaceValue::F32(42.)]);

assert_eq!(to_interface_value(&input).unwrap(), output);
}
Expand All @@ -527,7 +538,7 @@ mod tests {
}

let input = S { x: 7, y: 42. };
let output = InterfaceValue::Record(vec![InterfaceValue::S8(7), InterfaceValue::F32(42.)]);
let output = InterfaceValue::Record(vec1![InterfaceValue::S8(7), InterfaceValue::F32(42.)]);

assert_eq!(to_interface_value(&input).unwrap(), output);
}
Expand All @@ -552,13 +563,13 @@ mod tests {
p1: Point { x: 1, y: 2, z: 3 },
p2: Point { x: 4, y: 5, z: 6 },
};
let output = InterfaceValue::Record(vec![
InterfaceValue::Record(vec![
let output = InterfaceValue::Record(vec1![
InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::I32(2),
InterfaceValue::I32(3),
]),
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::I32(4),
InterfaceValue::I32(5),
InterfaceValue::I32(6),
Expand Down
2 changes: 2 additions & 0 deletions lib/interface-types/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,7 @@ pub enum InterfaceType {
#[derive(PartialEq, Debug, Clone)]
pub struct RecordType {
/// Types representing the fields.
/// A record must have at least one field, hence the
/// [`Vec1`][crate::vec1::Vec1].
pub fields: Vec1<InterfaceType>,
}
13 changes: 7 additions & 6 deletions lib/interface-types/src/values.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Defines WIT values and associated operations.
use crate::{
errors::WasmValueNativeCastError,
types::{InterfaceType, RecordType},
{errors::WasmValueNativeCastError, vec1::Vec1},
vec1::Vec1,
};
use std::{convert::TryFrom, slice::Iter};

Expand Down Expand Up @@ -53,7 +54,7 @@ pub enum InterfaceValue {
I64(i64),

/// A record.
Record(Vec<InterfaceValue>),
Record(Vec1<InterfaceValue>),
}

impl From<&InterfaceValue> for InterfaceType {
Expand All @@ -73,7 +74,7 @@ impl From<&InterfaceValue> for InterfaceType {
//InterfaceValue::Anyref(_) => Self::Anyref,
InterfaceValue::I32(_) => Self::I32,
InterfaceValue::I64(_) => Self::I64,
InterfaceValue::Record(values) => Self::Record(values.into()),
InterfaceValue::Record(values) => Self::Record((&**values).into()),
}
}
}
Expand Down Expand Up @@ -217,7 +218,7 @@ mod tests {
#[allow(non_snake_case)]
fn interface_type_from_interface_value__record() {
assert_eq!(
InterfaceType::from(&InterfaceValue::Record(vec![
InterfaceType::from(&InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::S8(2)
])),
Expand All @@ -227,9 +228,9 @@ mod tests {
);

assert_eq!(
InterfaceType::from(&InterfaceValue::Record(vec![
InterfaceType::from(&InterfaceValue::Record(vec1![
InterfaceValue::I32(1),
InterfaceValue::Record(vec![
InterfaceValue::Record(vec1![
InterfaceValue::String("a".to_string()),
InterfaceValue::F64(42.)
]),
Expand Down
Loading

0 comments on commit 4c2fb95

Please sign in to comment.