wasm/execution/checked/
value.rs

1use crate::{
2    addrs::FuncAddr,
3    value::{ExternAddr, Ref, ValueTypeMismatchError, F32, F64},
4    RefType, Value,
5};
6
7use super::{AbstractStored, Stored};
8
9/// A stored variant of [`Value`]
10#[derive(Clone, Copy, Debug, PartialEq)]
11pub enum StoredValue {
12    I32(u32),
13    I64(u64),
14    F32(F32),
15    F64(F64),
16    V128([u8; 16]),
17    Ref(StoredRef),
18}
19
20impl AbstractStored for StoredValue {
21    type BareTy = Value;
22
23    unsafe fn from_bare(bare_value: Self::BareTy, id: crate::StoreId) -> Self {
24        match bare_value {
25            Value::I32(x) => Self::I32(x),
26            Value::I64(x) => Self::I64(x),
27            Value::F32(x) => Self::F32(x),
28            Value::F64(x) => Self::F64(x),
29            Value::V128(x) => Self::V128(x),
30            Value::Ref(r#ref) => {
31                // SAFETY: Upheld by the caller
32                let stored_ref = unsafe { StoredRef::from_bare(r#ref, id) };
33                Self::Ref(stored_ref)
34            }
35        }
36    }
37
38    fn id(&self) -> Option<crate::StoreId> {
39        match self {
40            Self::Ref(r#ref) => r#ref.id(),
41            _ => None,
42        }
43    }
44
45    fn into_bare(self) -> Self::BareTy {
46        match self {
47            Self::I32(x) => Value::I32(x),
48            Self::I64(x) => Value::I64(x),
49            Self::F32(x) => Value::F32(x),
50            Self::F64(x) => Value::F64(x),
51            Self::V128(x) => Value::V128(x),
52            Self::Ref(stored_ref) => Value::Ref(stored_ref.into_bare()),
53        }
54    }
55}
56
57/// A stored variant of [`Ref`]
58#[derive(Clone, Copy, Debug, PartialEq)]
59pub enum StoredRef {
60    Null(RefType),
61    Func(Stored<FuncAddr>),
62    /// We do not wrap [`ExternAddr`]s in a [`Stored`] object because they are
63    /// not stored in the [`Store`](crate::Store).
64    Extern(ExternAddr),
65}
66
67impl AbstractStored for StoredRef {
68    type BareTy = Ref;
69
70    unsafe fn from_bare(bare_value: Self::BareTy, id: crate::StoreId) -> Self {
71        match bare_value {
72            Ref::Null(ref_type) => Self::Null(ref_type),
73            Ref::Func(func_addr) => {
74                // SAFETY: Upheld by the caller
75                let stored_func_addr = unsafe { Stored::from_bare(func_addr, id) };
76                Self::Func(stored_func_addr)
77            }
78            Ref::Extern(extern_addr) => Self::Extern(extern_addr),
79        }
80    }
81
82    fn id(&self) -> Option<crate::StoreId> {
83        match self {
84            StoredRef::Func(stored_func_addr) => stored_func_addr.id(),
85            StoredRef::Null(_) | StoredRef::Extern(_) => None,
86        }
87    }
88
89    fn into_bare(self) -> Self::BareTy {
90        match self {
91            Self::Null(ref_type) => Ref::Null(ref_type),
92            Self::Func(stored_func_addr) => Ref::Func(stored_func_addr.into_bare()),
93            Self::Extern(extern_addr) => Ref::Extern(extern_addr),
94        }
95    }
96}
97
98impl From<u32> for StoredValue {
99    fn from(value: u32) -> Self {
100        StoredValue::I32(value)
101    }
102}
103impl TryFrom<StoredValue> for u32 {
104    type Error = ValueTypeMismatchError;
105
106    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
107        match value {
108            StoredValue::I32(value) => Ok(value),
109            _ => Err(ValueTypeMismatchError),
110        }
111    }
112}
113
114impl From<i32> for StoredValue {
115    fn from(value: i32) -> Self {
116        StoredValue::I32(u32::from_le_bytes(value.to_le_bytes()))
117    }
118}
119impl TryFrom<StoredValue> for i32 {
120    type Error = ValueTypeMismatchError;
121
122    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
123        match value {
124            StoredValue::I32(value) => Ok(i32::from_le_bytes(value.to_le_bytes())),
125            _ => Err(ValueTypeMismatchError),
126        }
127    }
128}
129
130impl From<u64> for StoredValue {
131    fn from(value: u64) -> Self {
132        StoredValue::I64(value)
133    }
134}
135impl TryFrom<StoredValue> for u64 {
136    type Error = ValueTypeMismatchError;
137
138    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
139        match value {
140            StoredValue::I64(value) => Ok(value),
141            _ => Err(ValueTypeMismatchError),
142        }
143    }
144}
145
146impl From<i64> for StoredValue {
147    fn from(value: i64) -> Self {
148        StoredValue::I64(u64::from_le_bytes(value.to_le_bytes()))
149    }
150}
151impl TryFrom<StoredValue> for i64 {
152    type Error = ValueTypeMismatchError;
153
154    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
155        match value {
156            StoredValue::I64(value) => Ok(i64::from_le_bytes(value.to_le_bytes())),
157            _ => Err(ValueTypeMismatchError),
158        }
159    }
160}
161
162impl From<F32> for StoredValue {
163    fn from(value: F32) -> Self {
164        StoredValue::F32(value)
165    }
166}
167impl TryFrom<StoredValue> for F32 {
168    type Error = ValueTypeMismatchError;
169
170    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
171        match value {
172            StoredValue::F32(value) => Ok(value),
173            _ => Err(ValueTypeMismatchError),
174        }
175    }
176}
177
178impl From<F64> for StoredValue {
179    fn from(value: F64) -> Self {
180        StoredValue::F64(value)
181    }
182}
183impl TryFrom<StoredValue> for F64 {
184    type Error = ValueTypeMismatchError;
185
186    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
187        match value {
188            StoredValue::F64(value) => Ok(value),
189            _ => Err(ValueTypeMismatchError),
190        }
191    }
192}
193
194impl From<[u8; 16]> for StoredValue {
195    fn from(value: [u8; 16]) -> Self {
196        StoredValue::V128(value)
197    }
198}
199impl TryFrom<StoredValue> for [u8; 16] {
200    type Error = ValueTypeMismatchError;
201
202    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
203        match value {
204            StoredValue::V128(value) => Ok(value),
205            _ => Err(ValueTypeMismatchError),
206        }
207    }
208}
209
210impl From<StoredRef> for StoredValue {
211    fn from(value: StoredRef) -> Self {
212        StoredValue::Ref(value)
213    }
214}
215impl TryFrom<StoredValue> for StoredRef {
216    type Error = ValueTypeMismatchError;
217
218    fn try_from(value: StoredValue) -> Result<Self, Self::Error> {
219        match value {
220            StoredValue::Ref(value) => Ok(value),
221            _ => Err(ValueTypeMismatchError),
222        }
223    }
224}