1use core::alloc::Layout;
2use core::fmt;
3
4use align_address::usize_is_aligned_to;
5
6use crate::PAGE_SIZE;
7
8#[non_exhaustive]
10#[derive(Clone, PartialEq, Eq, Debug)]
11pub struct PageLayoutError;
12
13impl fmt::Display for PageLayoutError {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        f.write_str("invalid parameters to PageLayout::from_size_align")
16    }
17}
18
19#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
23pub struct PageLayout(Layout);
24
25impl PageLayout {
26    #[inline]
40    pub const fn from_size_align(size: usize, align: usize) -> Result<Self, PageLayoutError> {
41        if !usize_is_aligned_to(size, PAGE_SIZE) {
42            return Err(PageLayoutError);
43        }
44
45        if !usize_is_aligned_to(align, PAGE_SIZE) {
46            return Err(PageLayoutError);
47        }
48
49        match Layout::from_size_align(size, align) {
50            Ok(layout) => Ok(Self(layout)),
51            Err(_) => Err(PageLayoutError),
52        }
53    }
54
55    #[must_use]
61    #[inline]
62    pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
63        unsafe { Self(Layout::from_size_align_unchecked(size, align)) }
65    }
66
67    #[inline]
69    pub const fn from_size(size: usize) -> Result<Self, PageLayoutError> {
70        Self::from_size_align(size, PAGE_SIZE)
71    }
72
73    #[must_use]
75    #[inline]
76    pub const fn size(&self) -> usize {
77        self.0.size()
78    }
79
80    #[must_use]
82    #[inline]
83    pub const fn align(&self) -> usize {
84        self.0.align()
85    }
86}
87
88impl TryFrom<Layout> for PageLayout {
89    type Error = PageLayoutError;
90
91    #[inline]
92    fn try_from(value: Layout) -> Result<Self, Self::Error> {
93        Self::from_size_align(value.size(), value.align())
94    }
95}
96
97impl From<PageLayout> for Layout {
98    #[inline]
99    fn from(value: PageLayout) -> Self {
100        value.0
101    }
102}