use std::alloc::Layout;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SizeClass {
S8 = 0,
S16 = 1,
S32 = 2,
S64 = 3,
S128 = 4,
S256 = 5,
S512 = 6,
S1024 = 7,
S2048 = 8,
}
impl SizeClass {
#[inline(always)]
pub const fn size(self) -> usize {
match self {
SizeClass::S8 => 8,
SizeClass::S16 => 16,
SizeClass::S32 => 32,
SizeClass::S64 => 64,
SizeClass::S128 => 128,
SizeClass::S256 => 256,
SizeClass::S512 => 512,
SizeClass::S1024 => 1024,
SizeClass::S2048 => 2048,
}
}
#[inline(always)]
pub const fn align(self) -> usize {
match self {
SizeClass::S8 => 8,
SizeClass::S16 => 16,
SizeClass::S32 => 32,
SizeClass::S64 => 64,
SizeClass::S128 => 128,
SizeClass::S256 => 256,
SizeClass::S512 => 512,
SizeClass::S1024 => 1024,
SizeClass::S2048 => 2048,
}
}
#[inline(always)]
pub const fn layout(self) -> Layout {
unsafe { Layout::from_size_align_unchecked(self.size(), self.align()) }
}
#[inline(always)]
pub fn for_size(size: usize) -> Option<Self> {
match size {
0..=8 => Some(SizeClass::S8),
9..=16 => Some(SizeClass::S16),
17..=32 => Some(SizeClass::S32),
33..=64 => Some(SizeClass::S64),
65..=128 => Some(SizeClass::S128),
129..=256 => Some(SizeClass::S256),
257..=512 => Some(SizeClass::S512),
513..=1024 => Some(SizeClass::S1024),
1025..=2048 => Some(SizeClass::S2048),
_ => None,
}
}
#[inline(always)]
pub const fn all() -> [Self; 9] {
[
SizeClass::S8,
SizeClass::S16,
SizeClass::S32,
SizeClass::S64,
SizeClass::S128,
SizeClass::S256,
SizeClass::S512,
SizeClass::S1024,
SizeClass::S2048,
]
}
}
pub mod common {
use super::*;
pub const U64: Layout = Layout::new::<u64>();
pub const USIZE: Layout = Layout::new::<usize>();
pub const F64: Layout = Layout::new::<f64>();
pub const F32: Layout = Layout::new::<f32>();
pub const U8X16: Layout = Layout::new::<[u8; 16]>();
pub const U32X4: Layout = Layout::new::<[u32; 4]>();
pub const F32X4: Layout = Layout::new::<[f32; 4]>();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_size_class_sizes() {
assert_eq!(SizeClass::S8.size(), 8);
assert_eq!(SizeClass::S64.size(), 64);
assert_eq!(SizeClass::S1024.size(), 1024);
}
#[test]
fn test_size_classification() {
assert_eq!(SizeClass::for_size(8), Some(SizeClass::S8));
assert_eq!(SizeClass::for_size(16), Some(SizeClass::S16));
assert_eq!(SizeClass::for_size(100), Some(SizeClass::S128));
assert_eq!(SizeClass::for_size(3000), None);
}
#[test]
fn test_layout_validity() {
for class in SizeClass::all() {
let layout = class.layout();
assert!(layout.size() >= 1);
assert!(layout.align().is_power_of_two());
assert!(layout.size() % layout.align() == 0);
}
}
}