use crate::ValRaw; use core::mem::{self, MaybeUninit}; use core::slice; fn assert_raw_slice_compat() { assert!(mem::size_of::() % mem::size_of::() == 0); assert!(mem::align_of::() == mem::align_of::()); } /// Converts a `::Lower` representation to a slice of /// `ValRaw`. pub unsafe fn storage_as_slice(storage: &T) -> &[ValRaw] { assert_raw_slice_compat::(); unsafe { slice::from_raw_parts( (storage as *const T).cast(), mem::size_of_val(storage) / mem::size_of::(), ) } } /// Same as `storage_as_slice`, but mutable. pub unsafe fn storage_as_slice_mut(storage: &mut MaybeUninit) -> &mut [MaybeUninit] { assert_raw_slice_compat::(); unsafe { slice::from_raw_parts_mut( (storage as *mut MaybeUninit).cast(), mem::size_of_val(storage) / mem::size_of::(), ) } } /// Same as `storage_as_slice`, but in reverse and mutable. pub unsafe fn slice_to_storage_mut(slice: &mut [MaybeUninit]) -> &mut MaybeUninit { assert_raw_slice_compat::(); // This is an actual runtime assertion which if performance calls for we may // need to relax to a debug assertion. This notably tries to ensure that we // stay within the bounds of the number of actual values given rather than // reading past the end of an array. This shouldn't actually trip unless // there's a bug in Wasmtime though. assert!( mem::size_of_val(slice) >= mem::size_of::(), "needed {}; got {}", mem::size_of::(), mem::size_of_val(slice) ); unsafe { &mut *slice.as_mut_ptr().cast() } } /// Same as `storage_as_slice`, but in reverse pub unsafe fn slice_to_storage(slice: &[ValRaw]) -> &T { assert_raw_slice_compat::(); // See notes above in `slice_to_storage_mut` about how this is an actual // runtime assertion. assert!( mem::size_of_val(slice) >= mem::size_of::(), "needed {}; got {}", mem::size_of::(), mem::size_of_val(slice) ); unsafe { &*slice.as_ptr().cast() } }