wasmtime/runtime/component/
storage.rs

1use crate::ValRaw;
2use core::mem::{self, MaybeUninit};
3use core::slice;
4
5fn 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`.
12pub 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.
24pub 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.
36pub 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")]
56pub 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}