2020-03-30 08:32:31 +02:00
|
|
|
//! Defines WIT values and associated operations.
|
2020-02-13 14:34:45 +01:00
|
|
|
|
2020-04-09 11:23:26 +02:00
|
|
|
use crate::{
|
2020-04-09 12:10:48 +02:00
|
|
|
errors::WasmValueNativeCastError,
|
2020-04-09 11:23:26 +02:00
|
|
|
types::{InterfaceType, RecordType},
|
2020-04-09 12:10:48 +02:00
|
|
|
vec1::Vec1,
|
2020-04-09 11:23:26 +02:00
|
|
|
};
|
2020-04-02 11:55:20 +02:00
|
|
|
use std::{convert::TryFrom, slice::Iter};
|
2019-09-26 14:14:46 +02:00
|
|
|
|
2020-04-02 13:53:10 +02:00
|
|
|
#[cfg(feature = "serde")]
|
2020-04-09 11:23:26 +02:00
|
|
|
pub use crate::serde::{de::from_interface_values, ser::to_interface_value};
|
2020-04-02 13:53:10 +02:00
|
|
|
|
2020-03-30 08:32:31 +02:00
|
|
|
/// A WIT value.
|
2019-09-26 14:14:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum InterfaceValue {
|
2020-03-30 08:32:31 +02:00
|
|
|
/// A 8-bits signed integer.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
S8(i8),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 16-bits signed integer.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
S16(i16),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 32-bits signed integer.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
S32(i32),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 64-bits signed integer.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
S64(i64),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 8-bits unsigned integer.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
U8(u8),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 16-bits unsigned integer.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
U16(u16),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 32-bits unsigned integer.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
U32(u32),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 64-bits unsigned integer.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
U64(u64),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 32-bits float.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
F32(f32),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 64-bits float.
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
F64(f64),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A string.
|
2019-09-26 14:14:46 +02:00
|
|
|
String(String),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
2020-07-09 02:46:54 +03:00
|
|
|
/// A byte array.
|
|
|
|
ByteArray(Vec<u8>),
|
|
|
|
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
//Anyref(?),
|
2020-03-30 08:32:31 +02:00
|
|
|
/// A 32-bits integer (as defined in WebAssembly core).
|
2019-09-26 14:14:46 +02:00
|
|
|
I32(i32),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A 64-bits integer (as defiend in WebAssembly core).
|
2019-09-26 14:14:46 +02:00
|
|
|
I64(i64),
|
2020-03-30 08:32:31 +02:00
|
|
|
|
|
|
|
/// A record.
|
2020-04-09 12:10:48 +02:00
|
|
|
Record(Vec1<InterfaceValue>),
|
2019-09-26 14:14:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&InterfaceValue> for InterfaceType {
|
|
|
|
fn from(value: &InterfaceValue) -> Self {
|
|
|
|
match value {
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
InterfaceValue::S8(_) => Self::S8,
|
|
|
|
InterfaceValue::S16(_) => Self::S16,
|
|
|
|
InterfaceValue::S32(_) => Self::S32,
|
|
|
|
InterfaceValue::S64(_) => Self::S64,
|
|
|
|
InterfaceValue::U8(_) => Self::U8,
|
|
|
|
InterfaceValue::U16(_) => Self::U16,
|
|
|
|
InterfaceValue::U32(_) => Self::U32,
|
|
|
|
InterfaceValue::U64(_) => Self::U64,
|
|
|
|
InterfaceValue::F32(_) => Self::F32,
|
|
|
|
InterfaceValue::F64(_) => Self::F64,
|
2019-09-26 14:14:46 +02:00
|
|
|
InterfaceValue::String(_) => Self::String,
|
2020-07-09 02:46:54 +03:00
|
|
|
InterfaceValue::ByteArray(_) => Self::ByteArray,
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
//InterfaceValue::Anyref(_) => Self::Anyref,
|
2019-09-26 14:14:46 +02:00
|
|
|
InterfaceValue::I32(_) => Self::I32,
|
|
|
|
InterfaceValue::I64(_) => Self::I64,
|
2020-04-09 12:10:48 +02:00
|
|
|
InterfaceValue::Record(values) => Self::Record((&**values).into()),
|
2019-09-26 14:14:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for InterfaceValue {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::I32(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-02 11:55:54 +02:00
|
|
|
impl From<&Vec<InterfaceValue>> for RecordType {
|
|
|
|
fn from(values: &Vec<InterfaceValue>) -> Self {
|
|
|
|
RecordType {
|
2020-04-03 16:13:44 +02:00
|
|
|
fields: Vec1::new(values.iter().map(Into::into).collect())
|
|
|
|
.expect("Record must have at least one field, zero given."),
|
2020-04-02 11:55:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 08:32:31 +02:00
|
|
|
/// Represents a native type supported by WIT.
|
2020-03-10 15:41:49 +01:00
|
|
|
pub trait NativeType {
|
2020-03-30 08:32:31 +02:00
|
|
|
/// The associated interface type that maps to the native type.
|
2020-03-10 15:41:49 +01:00
|
|
|
const INTERFACE_TYPE: InterfaceType;
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! native {
|
|
|
|
($native_type:ty, $variant:ident) => {
|
|
|
|
impl NativeType for $native_type {
|
|
|
|
const INTERFACE_TYPE: InterfaceType = InterfaceType::$variant;
|
|
|
|
}
|
|
|
|
|
2019-09-26 14:14:46 +02:00
|
|
|
impl From<$native_type> for InterfaceValue {
|
|
|
|
fn from(n: $native_type) -> Self {
|
2020-03-10 15:41:49 +01:00
|
|
|
Self::$variant(n)
|
2019-09-26 14:14:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&InterfaceValue> for $native_type {
|
2020-03-10 15:41:49 +01:00
|
|
|
type Error = WasmValueNativeCastError;
|
2019-09-26 14:14:46 +02:00
|
|
|
|
|
|
|
fn try_from(w: &InterfaceValue) -> Result<Self, Self::Error> {
|
|
|
|
match w {
|
2020-03-10 15:41:49 +01:00
|
|
|
InterfaceValue::$variant(n) => Ok(n.clone()),
|
|
|
|
_ => Err(WasmValueNativeCastError {
|
|
|
|
from: w.into(),
|
|
|
|
to: <$native_type>::INTERFACE_TYPE,
|
|
|
|
}),
|
2019-09-26 14:14:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-03-10 15:41:49 +01:00
|
|
|
native!(i8, S8);
|
|
|
|
native!(i16, S16);
|
2020-03-30 08:32:31 +02:00
|
|
|
native!(i32, I32);
|
|
|
|
native!(i64, I64);
|
2020-03-10 15:41:49 +01:00
|
|
|
native!(u8, U8);
|
|
|
|
native!(u16, U16);
|
|
|
|
native!(u32, U32);
|
|
|
|
native!(u64, U64);
|
|
|
|
native!(f32, F32);
|
|
|
|
native!(f64, F64);
|
|
|
|
native!(String, String);
|
2020-07-09 02:46:54 +03:00
|
|
|
native!(Vec<u8>, ByteArray);
|
2020-03-30 08:32:31 +02:00
|
|
|
|
2020-04-02 11:55:20 +02:00
|
|
|
/// 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> {
|
2020-04-03 16:22:26 +02:00
|
|
|
match self.iterators.last_mut()?.next() {
|
2020-04-02 11:55:20 +02:00
|
|
|
// 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(values)) => {
|
|
|
|
self.iterators.push(values.iter());
|
|
|
|
self.next()
|
|
|
|
}
|
|
|
|
|
|
|
|
// A regular item.
|
|
|
|
e @ Some(_) => e,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 08:32:31 +02:00
|
|
|
#[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!(
|
2020-04-09 12:10:48 +02:00
|
|
|
InterfaceType::from(&InterfaceValue::Record(vec1![
|
2020-03-30 08:32:31 +02:00
|
|
|
InterfaceValue::I32(1),
|
|
|
|
InterfaceValue::S8(2)
|
|
|
|
])),
|
|
|
|
InterfaceType::Record(RecordType {
|
2020-04-03 16:13:44 +02:00
|
|
|
fields: vec1![InterfaceType::I32, InterfaceType::S8]
|
2020-03-30 08:32:31 +02:00
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_eq!(
|
2020-04-09 12:10:48 +02:00
|
|
|
InterfaceType::from(&InterfaceValue::Record(vec1![
|
2020-03-30 08:32:31 +02:00
|
|
|
InterfaceValue::I32(1),
|
2020-04-09 12:10:48 +02:00
|
|
|
InterfaceValue::Record(vec1![
|
2020-03-30 08:32:31 +02:00
|
|
|
InterfaceValue::String("a".to_string()),
|
|
|
|
InterfaceValue::F64(42.)
|
|
|
|
]),
|
|
|
|
InterfaceValue::S8(2)
|
|
|
|
])),
|
|
|
|
InterfaceType::Record(RecordType {
|
2020-04-03 16:13:44 +02:00
|
|
|
fields: vec1![
|
2020-03-30 08:32:31 +02:00
|
|
|
InterfaceType::I32,
|
|
|
|
InterfaceType::Record(RecordType {
|
2020-04-03 16:13:44 +02:00
|
|
|
fields: vec1![InterfaceType::String, InterfaceType::F64]
|
2020-03-30 08:32:31 +02:00
|
|
|
}),
|
|
|
|
InterfaceType::S8
|
|
|
|
]
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|