1use {
2 crate::{
3 decode::{Decode, DecodeError, Decoder},
4 downcast::{DowncastMut, DowncastRef},
5 extern_ref::UnguardedExternRef,
6 func_ref::UnguardedFuncRef,
7 store::{Handle, Store, StoreId, UnguardedHandle},
8 val::{UnguardedVal, Val, ValType},
9 },
10 std::{error::Error, fmt},
11};
12
13#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
15#[repr(transparent)]
16pub struct Global(pub(crate) Handle<GlobalEntity>);
17
18impl Global {
19 pub fn new(store: &mut Store, type_: GlobalType, val: Val) -> Result<Self, GlobalError> {
31 unsafe { Global::new_unguarded(store, type_, val.to_unguarded(store.id())) }
32 }
33
34 unsafe fn new_unguarded(
36 store: &mut Store,
37 type_: GlobalType,
38 val: UnguardedVal,
39 ) -> Result<Self, GlobalError> {
40 match (type_.val, val) {
41 (ValType::I32, UnguardedVal::I32(val)) => Ok(Self(
42 store.insert_global(GlobalEntity::I32(GlobalEntityT::new(type_.mut_, val))),
43 )),
44 (ValType::I64, UnguardedVal::I64(val)) => Ok(Self(
45 store.insert_global(GlobalEntity::I64(GlobalEntityT::new(type_.mut_, val))),
46 )),
47 (ValType::F32, UnguardedVal::F32(val)) => Ok(Self(
48 store.insert_global(GlobalEntity::F32(GlobalEntityT::new(type_.mut_, val))),
49 )),
50 (ValType::F64, UnguardedVal::F64(val)) => Ok(Self(
51 store.insert_global(GlobalEntity::F64(GlobalEntityT::new(type_.mut_, val))),
52 )),
53 (ValType::FuncRef, UnguardedVal::FuncRef(val)) => Ok(Self(
54 store.insert_global(GlobalEntity::FuncRef(GlobalEntityT::new(type_.mut_, val))),
55 )),
56 (ValType::ExternRef, UnguardedVal::ExternRef(val)) => Ok(Self(
57 store.insert_global(GlobalEntity::ExternRef(GlobalEntityT::new(type_.mut_, val))),
58 )),
59 _ => Err(GlobalError::ValTypeMismatch),
60 }
61 }
62
63 pub fn type_(self, store: &Store) -> GlobalType {
65 match self.0.as_ref(store) {
66 GlobalEntity::I32(global) => GlobalType {
67 mut_: global.mut_(),
68 val: ValType::I32,
69 },
70 GlobalEntity::I64(global) => GlobalType {
71 mut_: global.mut_(),
72 val: ValType::I64,
73 },
74 GlobalEntity::F32(global) => GlobalType {
75 mut_: global.mut_(),
76 val: ValType::F32,
77 },
78 GlobalEntity::F64(global) => GlobalType {
79 mut_: global.mut_(),
80 val: ValType::F64,
81 },
82 GlobalEntity::FuncRef(global) => GlobalType {
83 mut_: global.mut_(),
84 val: ValType::FuncRef,
85 },
86 GlobalEntity::ExternRef(global) => GlobalType {
87 mut_: global.mut_(),
88 val: ValType::ExternRef,
89 },
90 }
91 }
92
93 pub fn get(self, store: &Store) -> Val {
95 unsafe { Val::from_unguarded(self.get_unguarded(store), store.id()) }
96 }
97
98 fn get_unguarded(self, store: &Store) -> UnguardedVal {
100 match self.0.as_ref(store) {
101 GlobalEntity::I32(global) => UnguardedVal::I32(global.get()),
102 GlobalEntity::I64(global) => UnguardedVal::I64(global.get()),
103 GlobalEntity::F32(global) => UnguardedVal::F32(global.get()),
104 GlobalEntity::F64(global) => UnguardedVal::F64(global.get()),
105 GlobalEntity::FuncRef(global) => UnguardedVal::FuncRef(global.get()),
106 GlobalEntity::ExternRef(global) => UnguardedVal::ExternRef(global.get()),
107 }
108 }
109
110 pub fn set(self, store: &mut Store, val: Val) -> Result<(), GlobalError> {
121 unsafe { self.set_unguarded(store, val.to_unguarded(store.id())) }
122 }
123
124 unsafe fn set_unguarded(self, store: &mut Store, val: UnguardedVal) -> Result<(), GlobalError> {
126 if self.type_(store).mut_ != Mut::Var {
127 return Err(GlobalError::Immutable);
128 }
129 match (self.0.as_mut(store), val) {
130 (GlobalEntity::I32(global), UnguardedVal::I32(val)) => Ok(global.set(val)),
131 (GlobalEntity::I64(global), UnguardedVal::I64(val)) => Ok(global.set(val)),
132 (GlobalEntity::F32(global), UnguardedVal::F32(val)) => Ok(global.set(val)),
133 (GlobalEntity::F64(global), UnguardedVal::F64(val)) => Ok(global.set(val)),
134 (GlobalEntity::FuncRef(global), UnguardedVal::FuncRef(val)) => Ok(global.set(val)),
135 (GlobalEntity::ExternRef(global), UnguardedVal::ExternRef(val)) => Ok(global.set(val)),
136 _ => Err(GlobalError::ValTypeMismatch),
137 }
138 }
139
140 pub(crate) unsafe fn from_unguarded(global: UnguardedGlobal, store_id: StoreId) -> Self {
146 Self(Handle::from_unguarded(global, store_id))
147 }
148
149 pub(crate) fn to_unguarded(self, store_id: StoreId) -> UnguardedGlobal {
155 self.0.to_unguarded(store_id).into()
156 }
157}
158
159pub(crate) type UnguardedGlobal = UnguardedHandle<GlobalEntity>;
161
162#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
164pub struct GlobalType {
165 pub mut_: Mut,
167 pub val: ValType,
169}
170
171impl Decode for GlobalType {
172 fn decode(decoder: &mut Decoder<'_>) -> Result<Self, DecodeError> {
173 let val = decoder.decode()?;
174 let mut_ = decoder.decode()?;
175 Ok(Self { val, mut_ })
176 }
177}
178
179#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
181pub enum Mut {
182 Const,
184 Var,
186}
187
188impl Decode for Mut {
189 fn decode(decoder: &mut Decoder<'_>) -> Result<Self, DecodeError> {
190 match decoder.read_byte()? {
191 0x00 => Ok(Self::Const),
192 0x01 => Ok(Self::Var),
193 _ => Err(DecodeError::new("malformed mutability")),
194 }
195 }
196}
197
198#[derive(Clone, Copy, Debug)]
200#[non_exhaustive]
201pub enum GlobalError {
202 Immutable,
203 ValTypeMismatch,
204}
205
206impl fmt::Display for GlobalError {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 match self {
209 GlobalError::Immutable => write!(f, "global is immutable"),
210 GlobalError::ValTypeMismatch => write!(f, "value type mismatch"),
211 }
212 }
213}
214
215impl Error for GlobalError {}
216
217#[derive(Debug)]
219pub(crate) enum GlobalEntity {
220 I32(GlobalEntityT<i32>),
221 I64(GlobalEntityT<i64>),
222 F32(GlobalEntityT<f32>),
223 F64(GlobalEntityT<f64>),
224 FuncRef(GlobalEntityT<UnguardedFuncRef>),
225 ExternRef(GlobalEntityT<UnguardedExternRef>),
226}
227
228impl GlobalEntity {
229 pub(crate) fn downcast_ref<T>(&self) -> Option<&GlobalEntityT<T>>
232 where
233 GlobalEntityT<T>: DowncastRef<Self>,
234 {
235 GlobalEntityT::downcast_ref(self)
236 }
237
238 pub(crate) fn downcast_mut<T>(&mut self) -> Option<&mut GlobalEntityT<T>>
241 where
242 GlobalEntityT<T>: DowncastMut<Self>,
243 {
244 GlobalEntityT::downcast_mut(self)
245 }
246}
247
248#[derive(Debug)]
250pub(crate) struct GlobalEntityT<T> {
251 mut_: Mut,
252 val: T,
253}
254
255impl<T> GlobalEntityT<T>
256where
257 T: Copy,
258{
259 fn new(mut_: Mut, val: T) -> Self {
261 Self { mut_, val }
262 }
263
264 fn mut_(&self) -> Mut {
266 self.mut_
267 }
268
269 pub(crate) fn get(&self) -> T {
271 self.val
272 }
273
274 pub(crate) fn set(&mut self, val: T) {
276 self.val = val;
277 }
278}
279
280impl DowncastRef<GlobalEntity> for GlobalEntityT<i32> {
281 fn downcast_ref(global: &GlobalEntity) -> Option<&GlobalEntityT<i32>> {
282 match global {
283 GlobalEntity::I32(global) => Some(global),
284 _ => None,
285 }
286 }
287}
288
289impl DowncastMut<GlobalEntity> for GlobalEntityT<i32> {
290 fn downcast_mut(global: &mut GlobalEntity) -> Option<&mut GlobalEntityT<i32>> {
291 match global {
292 GlobalEntity::I32(global) => Some(global),
293 _ => None,
294 }
295 }
296}
297
298impl DowncastRef<GlobalEntity> for GlobalEntityT<i64> {
299 fn downcast_ref(global: &GlobalEntity) -> Option<&GlobalEntityT<i64>> {
300 match global {
301 GlobalEntity::I64(global) => Some(global),
302 _ => None,
303 }
304 }
305}
306
307impl DowncastMut<GlobalEntity> for GlobalEntityT<i64> {
308 fn downcast_mut(global: &mut GlobalEntity) -> Option<&mut GlobalEntityT<i64>> {
309 match global {
310 GlobalEntity::I64(global) => Some(global),
311 _ => None,
312 }
313 }
314}
315
316impl DowncastRef<GlobalEntity> for GlobalEntityT<f32> {
317 fn downcast_ref(global: &GlobalEntity) -> Option<&GlobalEntityT<f32>> {
318 match global {
319 GlobalEntity::F32(global) => Some(global),
320 _ => None,
321 }
322 }
323}
324
325impl DowncastMut<GlobalEntity> for GlobalEntityT<f32> {
326 fn downcast_mut(global: &mut GlobalEntity) -> Option<&mut GlobalEntityT<f32>> {
327 match global {
328 GlobalEntity::F32(global) => Some(global),
329 _ => None,
330 }
331 }
332}
333
334impl DowncastRef<GlobalEntity> for GlobalEntityT<f64> {
335 fn downcast_ref(global: &GlobalEntity) -> Option<&GlobalEntityT<f64>> {
336 match global {
337 GlobalEntity::F64(global) => Some(global),
338 _ => None,
339 }
340 }
341}
342
343impl DowncastMut<GlobalEntity> for GlobalEntityT<f64> {
344 fn downcast_mut(global: &mut GlobalEntity) -> Option<&mut GlobalEntityT<f64>> {
345 match global {
346 GlobalEntity::F64(global) => Some(global),
347 _ => None,
348 }
349 }
350}
351
352impl DowncastRef<GlobalEntity> for GlobalEntityT<UnguardedFuncRef> {
353 fn downcast_ref(global: &GlobalEntity) -> Option<&GlobalEntityT<UnguardedFuncRef>> {
354 match global {
355 GlobalEntity::FuncRef(global) => Some(global),
356 _ => None,
357 }
358 }
359}
360
361impl DowncastMut<GlobalEntity> for GlobalEntityT<UnguardedFuncRef> {
362 fn downcast_mut(global: &mut GlobalEntity) -> Option<&mut GlobalEntityT<UnguardedFuncRef>> {
363 match global {
364 GlobalEntity::FuncRef(global) => Some(global),
365 _ => None,
366 }
367 }
368}
369
370impl DowncastRef<GlobalEntity> for GlobalEntityT<UnguardedExternRef> {
371 fn downcast_ref(global: &GlobalEntity) -> Option<&GlobalEntityT<UnguardedExternRef>> {
372 match global {
373 GlobalEntity::ExternRef(global) => Some(global),
374 _ => None,
375 }
376 }
377}
378
379impl DowncastMut<GlobalEntity> for GlobalEntityT<UnguardedExternRef> {
380 fn downcast_mut(global: &mut GlobalEntity) -> Option<&mut GlobalEntityT<UnguardedExternRef>> {
381 match global {
382 GlobalEntity::ExternRef(global) => Some(global),
383 _ => None,
384 }
385 }
386}