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}