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