wasmer_interface_types/
values.rs

1//! Defines WIT values and associated operations.
2
3use crate::{
4    errors::WasmValueNativeCastError,
5    types::{InterfaceType, RecordType},
6    vec1::Vec1,
7};
8use std::{convert::TryFrom, slice::Iter};
9
10#[cfg(feature = "serde")]
11pub use crate::serde::{de::from_interface_values, ser::to_interface_value};
12
13/// A WIT value.
14#[derive(Debug, Clone, PartialEq)]
15pub enum InterfaceValue {
16    /// A 8-bits signed integer.
17    S8(i8),
18
19    /// A 16-bits signed integer.
20    S16(i16),
21
22    /// A 32-bits signed integer.
23    S32(i32),
24
25    /// A 64-bits signed integer.
26    S64(i64),
27
28    /// A 8-bits unsigned integer.
29    U8(u8),
30
31    /// A 16-bits unsigned integer.
32    U16(u16),
33
34    /// A 32-bits unsigned integer.
35    U32(u32),
36
37    /// A 64-bits unsigned integer.
38    U64(u64),
39
40    /// A 32-bits float.
41    F32(f32),
42
43    /// A 64-bits float.
44    F64(f64),
45
46    /// A string.
47    String(String),
48
49    //Anyref(?),
50    /// A 32-bits integer (as defined in WebAssembly core).
51    I32(i32),
52
53    /// A 64-bits integer (as defiend in WebAssembly core).
54    I64(i64),
55
56    /// A record.
57    Record(Vec1<InterfaceValue>),
58}
59
60impl From<&InterfaceValue> for InterfaceType {
61    fn from(value: &InterfaceValue) -> Self {
62        match value {
63            InterfaceValue::S8(_) => Self::S8,
64            InterfaceValue::S16(_) => Self::S16,
65            InterfaceValue::S32(_) => Self::S32,
66            InterfaceValue::S64(_) => Self::S64,
67            InterfaceValue::U8(_) => Self::U8,
68            InterfaceValue::U16(_) => Self::U16,
69            InterfaceValue::U32(_) => Self::U32,
70            InterfaceValue::U64(_) => Self::U64,
71            InterfaceValue::F32(_) => Self::F32,
72            InterfaceValue::F64(_) => Self::F64,
73            InterfaceValue::String(_) => Self::String,
74            //InterfaceValue::Anyref(_) => Self::Anyref,
75            InterfaceValue::I32(_) => Self::I32,
76            InterfaceValue::I64(_) => Self::I64,
77            InterfaceValue::Record(values) => Self::Record((&**values).into()),
78        }
79    }
80}
81
82impl Default for InterfaceValue {
83    fn default() -> Self {
84        Self::I32(0)
85    }
86}
87
88impl From<&Vec<InterfaceValue>> for RecordType {
89    fn from(values: &Vec<InterfaceValue>) -> Self {
90        RecordType {
91            fields: Vec1::new(values.iter().map(Into::into).collect())
92                .expect("Record must have at least one field, zero given."),
93        }
94    }
95}
96
97/// Represents a native type supported by WIT.
98pub trait NativeType {
99    /// The associated interface type that maps to the native type.
100    const INTERFACE_TYPE: InterfaceType;
101}
102
103macro_rules! native {
104    ($native_type:ty, $variant:ident) => {
105        impl NativeType for $native_type {
106            const INTERFACE_TYPE: InterfaceType = InterfaceType::$variant;
107        }
108
109        impl From<$native_type> for InterfaceValue {
110            fn from(n: $native_type) -> Self {
111                Self::$variant(n)
112            }
113        }
114
115        impl TryFrom<&InterfaceValue> for $native_type {
116            type Error = WasmValueNativeCastError;
117
118            fn try_from(w: &InterfaceValue) -> Result<Self, Self::Error> {
119                match w {
120                    InterfaceValue::$variant(n) => Ok(n.clone()),
121                    _ => Err(WasmValueNativeCastError {
122                        from: w.into(),
123                        to: <$native_type>::INTERFACE_TYPE,
124                    }),
125                }
126            }
127        }
128    };
129}
130
131native!(i8, S8);
132native!(i16, S16);
133native!(i32, I32);
134native!(i64, I64);
135native!(u8, U8);
136native!(u16, U16);
137native!(u32, U32);
138native!(u64, U64);
139native!(f32, F32);
140native!(f64, F64);
141native!(String, String);
142
143/// Iterates over a vector of `InterfaceValues` but flatten all the
144/// values. So `I32(1), Record([I32(2), I32(3)]), I32(4)` will be
145/// iterated like `I32(1), I32(2), I32(3), I32(4)`.
146pub(crate) struct FlattenInterfaceValueIterator<'a> {
147    iterators: Vec<Iter<'a, InterfaceValue>>,
148}
149
150impl<'a> FlattenInterfaceValueIterator<'a> {
151    pub(crate) fn new(values: &'a [InterfaceValue]) -> Self {
152        Self {
153            iterators: vec![values.iter()],
154        }
155    }
156}
157
158impl<'a> Iterator for FlattenInterfaceValueIterator<'a> {
159    type Item = &'a InterfaceValue;
160
161    fn next(&mut self) -> Option<Self::Item> {
162        match self.iterators.last_mut()?.next() {
163            // End of the current iterator, go back to the previous
164            // one.
165            None => {
166                self.iterators.pop();
167                self.next()
168            }
169
170            // Recursively iterate over the record.
171            Some(InterfaceValue::Record(values)) => {
172                self.iterators.push(values.iter());
173                self.next()
174            }
175
176            // A regular item.
177            e @ Some(_) => e,
178        }
179    }
180}
181
182#[cfg(test)]
183mod tests {
184    use super::*;
185
186    macro_rules! value_to_type {
187        ($test_name:ident, $ty:ident, $value:expr) => {
188            #[test]
189            #[allow(non_snake_case)]
190            fn $test_name() {
191                assert_eq!(
192                    InterfaceType::from(&InterfaceValue::$ty($value)),
193                    InterfaceType::$ty
194                );
195            }
196        };
197    }
198
199    value_to_type!(interface_type_from_interface_value__s8, S8, 42);
200    value_to_type!(interface_type_from_interface_value__s16, S16, 42);
201    value_to_type!(interface_type_from_interface_value__s32, S32, 42);
202    value_to_type!(interface_type_from_interface_value__s64, S64, 42);
203    value_to_type!(interface_type_from_interface_value__u8, U8, 42);
204    value_to_type!(interface_type_from_interface_value__u16, U16, 42);
205    value_to_type!(interface_type_from_interface_value__u32, U32, 42);
206    value_to_type!(interface_type_from_interface_value__u64, U64, 42);
207    value_to_type!(interface_type_from_interface_value__f32, F32, 42.);
208    value_to_type!(interface_type_from_interface_value__f64, F64, 42.);
209    value_to_type!(
210        interface_type_from_interface_value__string,
211        String,
212        "foo".to_string()
213    );
214    value_to_type!(interface_type_from_interface_value__i32, I32, 42);
215    value_to_type!(interface_type_from_interface_value__i64, I64, 42);
216
217    #[test]
218    #[allow(non_snake_case)]
219    fn interface_type_from_interface_value__record() {
220        assert_eq!(
221            InterfaceType::from(&InterfaceValue::Record(vec1![
222                InterfaceValue::I32(1),
223                InterfaceValue::S8(2)
224            ])),
225            InterfaceType::Record(RecordType {
226                fields: vec1![InterfaceType::I32, InterfaceType::S8]
227            })
228        );
229
230        assert_eq!(
231            InterfaceType::from(&InterfaceValue::Record(vec1![
232                InterfaceValue::I32(1),
233                InterfaceValue::Record(vec1![
234                    InterfaceValue::String("a".to_string()),
235                    InterfaceValue::F64(42.)
236                ]),
237                InterfaceValue::S8(2)
238            ])),
239            InterfaceType::Record(RecordType {
240                fields: vec1![
241                    InterfaceType::I32,
242                    InterfaceType::Record(RecordType {
243                        fields: vec1![InterfaceType::String, InterfaceType::F64]
244                    }),
245                    InterfaceType::S8
246                ]
247            })
248        );
249    }
250}