1use 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#[derive(Debug, Clone, PartialEq)]
15pub enum InterfaceValue {
16 S8(i8),
18
19 S16(i16),
21
22 S32(i32),
24
25 S64(i64),
27
28 U8(u8),
30
31 U16(u16),
33
34 U32(u32),
36
37 U64(u64),
39
40 F32(f32),
42
43 F64(f64),
45
46 String(String),
48
49 I32(i32),
52
53 I64(i64),
55
56 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::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
97pub trait NativeType {
99 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
143pub(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 None => {
166 self.iterators.pop();
167 self.next()
168 }
169
170 Some(InterfaceValue::Record(values)) => {
172 self.iterators.push(values.iter());
173 self.next()
174 }
175
176 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}