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