nanvm_lib/mem/
field_layout.rs

1use core::{
2    alloc::Layout,
3    marker::PhantomData,
4    mem::{align_of, size_of},
5};
6
7use crate::common::usize::max;
8
9pub struct FieldLayout<T, A> {
10    pub align: usize,
11    pub size: usize,
12    _0: PhantomData<(T, A)>,
13}
14
15pub const fn align_to(i: usize, align: usize) -> usize {
16    let mask = align - 1;
17    (i + mask) & !mask
18}
19
20impl<T, A> FieldLayout<T, A> {
21    pub const fn align_to(adjacent_align: usize) -> FieldLayout<T, A> {
22        assert!(adjacent_align.is_power_of_two());
23        assert!(adjacent_align >= align_of::<A>());
24        FieldLayout {
25            align: max(align_of::<T>(), adjacent_align),
26            size: align_to(size_of::<T>(), adjacent_align),
27            _0: PhantomData,
28        }
29    }
30    #[inline(always)]
31    pub const unsafe fn to_adjacent(&self, r: &T) -> *const A {
32        unsafe { (r as *const T).byte_add(self.size) as *const _ }
33    }
34    #[inline(always)]
35    pub unsafe fn into_adjacent_mut(self, r: &mut T) -> *mut A {
36        unsafe { (r as *mut T).byte_add(self.size) as *mut _ }
37    }
38    #[allow(clippy::wrong_self_convention)]
39    #[inline(always)]
40    pub unsafe fn from_adjacent_mut(self, r: &mut A) -> *mut T {
41        unsafe { (r as *mut A).byte_sub(self.size) as *mut _ }
42    }
43    #[inline(always)]
44    pub const fn layout(&self, a_size: usize) -> Layout {
45        unsafe { Layout::from_size_align_unchecked(self.size + a_size, self.align) }
46    }
47}
48
49#[cfg(test)]
50mod test {
51    use wasm_bindgen_test::wasm_bindgen_test;
52
53    use super::FieldLayout;
54
55    const _A_4_1: FieldLayout<u32, u8> = FieldLayout::align_to(1);
56    const _: () = assert!(_A_4_1.align == 4 && _A_4_1.size == 4);
57
58    const _A_4_8: FieldLayout<u32, u8> = FieldLayout::align_to(8);
59    const _: () = assert!(_A_4_8.align == 8 && _A_4_8.size == 8);
60
61    const _A_1_4: FieldLayout<[u8; 3], u8> = FieldLayout::align_to(4);
62    const _: () = assert!(_A_1_4.align == 4 && _A_1_4.size == 4);
63
64    #[test]
65    #[should_panic]
66    #[wasm_bindgen_test]
67    fn test_invalid_align1() {
68        FieldLayout::<u32, u8>::align_to(3);
69    }
70
71    #[test]
72    #[should_panic]
73    #[wasm_bindgen_test]
74    fn test_invalid_align2() {
75        FieldLayout::<u32, u16>::align_to(1);
76    }
77}