1 use crate::ValRaw;
2 use core::mem::{self, MaybeUninit};
3 use core::slice;
4 
assert_raw_slice_compat<T>()5 fn assert_raw_slice_compat<T>() {
6     assert!(mem::size_of::<T>() % mem::size_of::<ValRaw>() == 0);
7     assert!(mem::align_of::<T>() == mem::align_of::<ValRaw>());
8 }
9 
10 /// Converts a `<T as ComponentType>::Lower` representation to a slice of
11 /// `ValRaw`.
storage_as_slice<T>(storage: &T) -> &[ValRaw]12 pub unsafe fn storage_as_slice<T>(storage: &T) -> &[ValRaw] {
13     assert_raw_slice_compat::<T>();
14 
15     unsafe {
16         slice::from_raw_parts(
17             (storage as *const T).cast(),
18             mem::size_of_val(storage) / mem::size_of::<ValRaw>(),
19         )
20     }
21 }
22 
23 /// Same as `storage_as_slice`, but mutable.
storage_as_slice_mut<T>(storage: &mut MaybeUninit<T>) -> &mut [MaybeUninit<ValRaw>]24 pub unsafe fn storage_as_slice_mut<T>(storage: &mut MaybeUninit<T>) -> &mut [MaybeUninit<ValRaw>] {
25     assert_raw_slice_compat::<T>();
26 
27     unsafe {
28         slice::from_raw_parts_mut(
29             (storage as *mut MaybeUninit<T>).cast(),
30             mem::size_of_val(storage) / mem::size_of::<ValRaw>(),
31         )
32     }
33 }
34 
35 /// Same as `storage_as_slice`, but in reverse and mutable.
slice_to_storage_mut<T>(slice: &mut [MaybeUninit<ValRaw>]) -> &mut MaybeUninit<T>36 pub unsafe fn slice_to_storage_mut<T>(slice: &mut [MaybeUninit<ValRaw>]) -> &mut MaybeUninit<T> {
37     assert_raw_slice_compat::<T>();
38 
39     // This is an actual runtime assertion which if performance calls for we may
40     // need to relax to a debug assertion. This notably tries to ensure that we
41     // stay within the bounds of the number of actual values given rather than
42     // reading past the end of an array. This shouldn't actually trip unless
43     // there's a bug in Wasmtime though.
44     assert!(
45         mem::size_of_val(slice) >= mem::size_of::<T>(),
46         "needed {}; got {}",
47         mem::size_of::<T>(),
48         mem::size_of_val(slice)
49     );
50 
51     unsafe { &mut *slice.as_mut_ptr().cast() }
52 }
53 
54 /// Same as `storage_as_slice`, but in reverse
slice_to_storage<T>(slice: &[ValRaw]) -> &T55 pub unsafe fn slice_to_storage<T>(slice: &[ValRaw]) -> &T {
56     assert_raw_slice_compat::<T>();
57 
58     // See notes above in `slice_to_storage_mut` about how this is an actual
59     // runtime assertion.
60     assert!(
61         mem::size_of_val(slice) >= mem::size_of::<T>(),
62         "needed {}; got {}",
63         mem::size_of::<T>(),
64         mem::size_of_val(slice)
65     );
66 
67     unsafe { &*slice.as_ptr().cast() }
68 }
69