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 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. 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. 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 55 #[cfg(feature = "component-model-async")] 56 pub unsafe fn slice_to_storage<T>(slice: &[ValRaw]) -> &T { 57 assert_raw_slice_compat::<T>(); 58 59 // See notes above in `slice_to_storage_mut` about how this is an actual 60 // runtime assertion. 61 assert!( 62 mem::size_of_val(slice) >= mem::size_of::<T>(), 63 "needed {}; got {}", 64 mem::size_of::<T>(), 65 mem::size_of_val(slice) 66 ); 67 68 unsafe { &*slice.as_ptr().cast() } 69 } 70