wasm/execution/checked/
interop.rs

1use crate::{
2    addrs::FuncAddr,
3    checked::{Stored, StoredRef, StoredValue},
4    interop::RefExtern,
5    value::{ValueTypeMismatchError, F32, F64},
6    NumType, RefType, ValType,
7};
8
9use alloc::{fmt::Debug, vec, vec::Vec};
10
11/// A stored variant of [`InteropValue`](crate::execution::interop::InteropValue)
12pub trait StoredInteropValue
13where
14    Self: Copy + Debug + PartialEq + TryFrom<StoredValue, Error = ValueTypeMismatchError>,
15    StoredValue: From<Self>,
16{
17    const TY: ValType;
18}
19
20impl StoredInteropValue for u32 {
21    const TY: ValType = ValType::NumType(NumType::I32);
22}
23
24impl StoredInteropValue for i32 {
25    const TY: ValType = ValType::NumType(NumType::I32);
26}
27
28impl StoredInteropValue for u64 {
29    const TY: ValType = ValType::NumType(NumType::I64);
30}
31
32impl StoredInteropValue for i64 {
33    const TY: ValType = ValType::NumType(NumType::I64);
34}
35
36impl StoredInteropValue for f32 {
37    const TY: ValType = ValType::NumType(NumType::F32);
38}
39
40impl StoredInteropValue for f64 {
41    const TY: ValType = ValType::NumType(NumType::F64);
42}
43
44impl StoredInteropValue for [u8; 16] {
45    const TY: ValType = ValType::VecType;
46}
47
48impl StoredInteropValue for StoredRefFunc {
49    const TY: ValType = ValType::RefType(RefType::FuncRef);
50}
51
52impl StoredInteropValue for RefExtern {
53    const TY: ValType = ValType::RefType(RefType::ExternRef);
54}
55
56impl From<f32> for StoredValue {
57    fn from(value: f32) -> Self {
58        F32(value).into()
59    }
60}
61
62impl TryFrom<StoredValue> for f32 {
63    type Error = ValueTypeMismatchError;
64
65    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
66        F32::try_from(value).map(|f| f.0)
67    }
68}
69
70impl From<f64> for StoredValue {
71    fn from(value: f64) -> Self {
72        F64(value).into()
73    }
74}
75
76impl TryFrom<StoredValue> for f64 {
77    type Error = ValueTypeMismatchError;
78
79    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
80        F64::try_from(value).map(|f| f.0)
81    }
82}
83
84#[derive(Debug, Copy, Clone, PartialEq)]
85pub struct StoredRefFunc(pub Option<Stored<FuncAddr>>);
86
87impl From<StoredRefFunc> for StoredValue {
88    fn from(value: StoredRefFunc) -> Self {
89        match value.0 {
90            Some(func_addr) => StoredValue::Ref(StoredRef::Func(func_addr)),
91            None => StoredValue::Ref(StoredRef::Null(RefType::FuncRef)),
92        }
93    }
94}
95impl TryFrom<StoredValue> for StoredRefFunc {
96    type Error = ValueTypeMismatchError;
97
98    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
99        match StoredRef::try_from(value)? {
100            StoredRef::Func(func_addr) => Ok(Self(Some(func_addr))),
101            StoredRef::Null(RefType::FuncRef) => Ok(Self(None)),
102            _ => Err(ValueTypeMismatchError),
103        }
104    }
105}
106
107impl From<RefExtern> for StoredValue {
108    fn from(value: RefExtern) -> Self {
109        match value.0 {
110            Some(extern_addr) => StoredValue::Ref(StoredRef::Extern(extern_addr)),
111            None => StoredValue::Ref(StoredRef::Null(RefType::ExternRef)),
112        }
113    }
114}
115
116impl TryFrom<StoredValue> for RefExtern {
117    type Error = ValueTypeMismatchError;
118
119    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
120        match value {
121            StoredValue::Ref(StoredRef::Extern(extern_addr)) => Ok(Self(Some(extern_addr))),
122            StoredValue::Ref(StoredRef::Null(RefType::ExternRef)) => Ok(Self(None)),
123            _ => Err(ValueTypeMismatchError),
124        }
125    }
126}
127
128/// A [StoredInteropValueList] is an iterable list of [StoredInteropValue]s (i.e. Rust types that can be converted into Wasm [StoredValue]s).
129pub trait StoredInteropValueList: Debug + Copy {
130    const TYS: &'static [ValType];
131
132    fn into_values(self) -> Vec<StoredValue>;
133
134    fn try_from_values(
135        values: impl ExactSizeIterator<Item = StoredValue>,
136    ) -> Result<Self, ValueTypeMismatchError>;
137}
138
139impl StoredInteropValueList for () {
140    const TYS: &'static [ValType] = &[];
141
142    fn into_values(self) -> Vec<StoredValue> {
143        Vec::new()
144    }
145
146    fn try_from_values(
147        values: impl ExactSizeIterator<Item = StoredValue>,
148    ) -> Result<Self, ValueTypeMismatchError> {
149        if values.len() != 0 {
150            return Err(ValueTypeMismatchError);
151        }
152
153        Ok(())
154    }
155}
156
157impl<A> StoredInteropValueList for A
158where
159    A: StoredInteropValue,
160    StoredValue: From<A>,
161{
162    const TYS: &'static [ValType] = &[A::TY];
163
164    fn into_values(self) -> Vec<StoredValue> {
165        vec![self.into()]
166    }
167
168    fn try_from_values(
169        mut values: impl ExactSizeIterator<Item = StoredValue>,
170    ) -> Result<Self, ValueTypeMismatchError> {
171        if values.len() != Self::TYS.len() {
172            return Err(ValueTypeMismatchError);
173        }
174
175        A::try_from(values.next().unwrap())
176    }
177}
178
179impl<A> StoredInteropValueList for (A,)
180where
181    A: StoredInteropValue,
182    StoredValue: From<A>,
183{
184    const TYS: &'static [ValType] = &[A::TY];
185
186    fn into_values(self) -> Vec<StoredValue> {
187        vec![self.0.into()]
188    }
189
190    fn try_from_values(
191        mut values: impl ExactSizeIterator<Item = StoredValue>,
192    ) -> Result<Self, ValueTypeMismatchError> {
193        if values.len() != Self::TYS.len() {
194            return Err(ValueTypeMismatchError);
195        }
196
197        Ok((A::try_from(values.next().unwrap())?,))
198    }
199}
200
201impl<A, B> StoredInteropValueList for (A, B)
202where
203    A: StoredInteropValue,
204    B: StoredInteropValue,
205    StoredValue: From<A> + From<B>,
206{
207    const TYS: &'static [ValType] = &[A::TY, B::TY];
208
209    fn into_values(self) -> Vec<StoredValue> {
210        vec![self.0.into(), self.1.into()]
211    }
212
213    fn try_from_values(
214        mut values: impl ExactSizeIterator<Item = StoredValue>,
215    ) -> Result<Self, ValueTypeMismatchError> {
216        if values.len() != Self::TYS.len() {
217            return Err(ValueTypeMismatchError);
218        }
219
220        Ok((
221            A::try_from(values.next().unwrap())?,
222            B::try_from(values.next().unwrap())?,
223        ))
224    }
225}
226
227impl<A, B, C> StoredInteropValueList for (A, B, C)
228where
229    A: StoredInteropValue,
230    B: StoredInteropValue,
231    C: StoredInteropValue,
232    StoredValue: From<A> + From<B> + From<C>,
233{
234    const TYS: &'static [ValType] = &[A::TY, B::TY, C::TY];
235
236    fn into_values(self) -> Vec<StoredValue> {
237        vec![self.0.into(), self.1.into(), self.2.into()]
238    }
239
240    fn try_from_values(
241        mut values: impl ExactSizeIterator<Item = StoredValue>,
242    ) -> Result<Self, ValueTypeMismatchError> {
243        if values.len() != Self::TYS.len() {
244            return Err(ValueTypeMismatchError);
245        }
246
247        Ok((
248            A::try_from(values.next().unwrap())?,
249            B::try_from(values.next().unwrap())?,
250            C::try_from(values.next().unwrap())?,
251        ))
252    }
253}