frozen_core/memmap/
page_size.rs1use crate::{
4 error::{FrozenError, FrozenResult},
5 hints,
6 memmap::err,
7};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
30#[repr(usize)]
31pub enum PageSize {
32 K4 = 0x1000,
34
35 K16 = 0x4000,
37
38 K64 = 0x10000,
40}
41
42impl PageSize {
43 #[inline]
45 pub const fn as_usize(self) -> usize {
46 self as usize
47 }
48
49 #[inline]
51 pub const fn as_u32(self) -> u32 {
52 self as usize as u32
53 }
54
55 #[inline]
57 pub const fn is_power_of_two(self) -> bool {
58 true
59 }
60
61 pub fn validate_platform(self) -> FrozenResult<Self> {
72 Self::validate_target_platform(self, std::env::consts::OS, std::env::consts::ARCH)
73 }
74
75 pub(crate) fn validate_target_platform(self, os: &str, arch: &str) -> FrozenResult<Self> {
76 let valid = match (os, arch) {
77 ("windows", _) => self == Self::K4,
78 ("macos", "aarch64") => self == Self::K16,
79 ("macos", "x86_64") => self == Self::K4,
80 ("linux", "x86" | "x86_64") => self == Self::K4,
81 ("linux", "aarch64") => matches!(self, Self::K4 | Self::K16 | Self::K64),
82 _ => false,
83 };
84
85 if hints::likely(valid) {
86 Ok(self)
87 } else {
88 err::raw_error(
89 err::INV,
90 format!(
91 "unsupported page size {} for target platform {os}/{arch}",
92 self.as_usize()
93 ),
94 )
95 }
96 }
97}
98
99impl From<PageSize> for usize {
100 #[inline]
101 fn from(ps: PageSize) -> Self {
102 ps as usize
103 }
104}
105
106impl From<PageSize> for u32 {
107 #[inline]
108 fn from(ps: PageSize) -> Self {
109 ps as usize as u32
110 }
111}
112
113impl From<PageSize> for u64 {
114 #[inline]
115 fn from(ps: PageSize) -> Self {
116 ps as usize as u64
117 }
118}
119
120impl core::fmt::Display for PageSize {
121 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
122 write!(f, "{}", self.as_usize())
123 }
124}
125
126impl TryFrom<usize> for PageSize {
127 type Error = FrozenError;
128
129 fn try_from(size: usize) -> Result<Self, Self::Error> {
130 match size {
131 0x1000 => Ok(Self::K4),
132 0x4000 => Ok(Self::K16),
133 0x10000 => Ok(Self::K64),
134 other => err::raw_error(err::INV, format!("unsupported page size: {other}")),
135 }
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn ok_page_size_conversions() {
145 assert_eq!(PageSize::K4.as_usize(), 0x1000);
146 assert_eq!(PageSize::K16.as_usize(), 0x4000);
147 assert_eq!(PageSize::K64.as_usize(), 0x10000);
148
149 assert_eq!(PageSize::K4.as_u32(), 0x1000);
150 assert_eq!(PageSize::K16.as_u32(), 0x4000);
151 assert_eq!(PageSize::K64.as_u32(), 0x10000);
152
153 assert_eq!(usize::from(PageSize::K4), 0x1000);
154 assert_eq!(u32::from(PageSize::K16), 0x4000);
155 assert_eq!(u64::from(PageSize::K64), 0x10000);
156
157 assert_eq!(PageSize::try_from(0x1000).unwrap(), PageSize::K4);
158 assert_eq!(PageSize::try_from(0x4000).unwrap(), PageSize::K16);
159 assert_eq!(PageSize::try_from(0x10000).unwrap(), PageSize::K64);
160
161 assert_eq!(format!("{}", PageSize::K4), "4096");
162 assert_eq!(format!("{}", PageSize::K16), "16384");
163 assert_eq!(format!("{}", PageSize::K64), "65536");
164
165 assert!(PageSize::K4.is_power_of_two());
166 assert!(PageSize::K16.is_power_of_two());
167 assert!(PageSize::K64.is_power_of_two());
168 }
169
170 #[test]
171 fn err_page_size_invalid_values() {
172 assert!(PageSize::try_from(0x0).is_err());
173 assert!(PageSize::try_from(0x400).is_err());
174 assert!(PageSize::try_from(0x800).is_err());
175 assert!(PageSize::try_from(0x1388).is_err());
176 assert!(PageSize::try_from(0x2000).is_err());
177 assert!(PageSize::try_from(0x8000).is_err());
178 assert!(PageSize::try_from(0x20000).is_err());
179 }
180
181 #[test]
182 fn ok_platform_validation_matrix() {
183 assert!(PageSize::K4.validate_target_platform("windows", "x86_64").is_ok());
185 assert!(PageSize::K4.validate_target_platform("windows", "aarch64").is_ok());
186 assert!(PageSize::K16.validate_target_platform("windows", "x86_64").is_err());
187 assert!(PageSize::K64.validate_target_platform("windows", "x86_64").is_err());
188
189 assert!(PageSize::K16.validate_target_platform("macos", "aarch64").is_ok());
191 assert!(PageSize::K4.validate_target_platform("macos", "aarch64").is_err());
192 assert!(PageSize::K64.validate_target_platform("macos", "aarch64").is_err());
193
194 assert!(PageSize::K4.validate_target_platform("macos", "x86_64").is_ok());
196 assert!(PageSize::K16.validate_target_platform("macos", "x86_64").is_err());
197 assert!(PageSize::K64.validate_target_platform("macos", "x86_64").is_err());
198
199 assert!(PageSize::K4.validate_target_platform("linux", "x86_64").is_ok());
201 assert!(PageSize::K4.validate_target_platform("linux", "x86").is_ok());
202 assert!(PageSize::K16.validate_target_platform("linux", "x86_64").is_err());
203 assert!(PageSize::K64.validate_target_platform("linux", "x86_64").is_err());
204
205 assert!(PageSize::K4.validate_target_platform("linux", "aarch64").is_ok());
207 assert!(PageSize::K16.validate_target_platform("linux", "aarch64").is_ok());
208 assert!(PageSize::K64.validate_target_platform("linux", "aarch64").is_ok());
209
210 assert!(PageSize::K4.validate_target_platform("freebsd", "x86_64").is_err());
212 assert!(PageSize::K4.validate_target_platform("unknown", "unknown").is_err());
213 }
214
215 #[test]
216 fn ok_current_platform_validation() {
217 #[cfg(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")))]
218 assert!(PageSize::K4.validate_platform().is_ok());
219
220 #[cfg(all(target_os = "linux", target_arch = "aarch64"))]
221 {
222 assert!(PageSize::K4.validate_platform().is_ok());
223 assert!(PageSize::K16.validate_platform().is_ok());
224 assert!(PageSize::K64.validate_platform().is_ok());
225 }
226
227 #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
228 {
229 assert!(PageSize::K16.validate_platform().is_ok());
230 assert!(PageSize::K4.validate_platform().is_err());
231 }
232
233 #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
234 {
235 assert!(PageSize::K4.validate_platform().is_ok());
236 assert!(PageSize::K16.validate_platform().is_err());
237 }
238
239 #[cfg(target_os = "windows")]
240 {
241 assert!(PageSize::K4.validate_platform().is_ok());
242 assert!(PageSize::K16.validate_platform().is_err());
243 }
244 }
245}