memkit 0.2.0-beta.1

Deterministic, intent-driven memory allocation for systems requiring predictable performance
Documentation
//! Size-class based allocation for common sizes.
//!
//! Provides fast allocation paths for frequently used sizes by pre-computing
//! layouts and using specialized allocation strategies.

use std::alloc::Layout;

/// Common size classes for fast allocation.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SizeClass {
    /// 8 bytes - small primitives, pointers
    S8 = 0,
    /// 16 bytes - two pointers, small structs
    S16 = 1,
    /// 32 bytes - medium structs
    S32 = 2,
    /// 64 bytes - cache line sized structs
    S64 = 3,
    /// 128 bytes - larger structs
    S128 = 4,
    /// 256 bytes - small arrays
    S256 = 5,
    /// 512 bytes - medium arrays
    S512 = 6,
    /// 1024 bytes - large arrays
    S1024 = 7,
    /// 2048 bytes - very large arrays
    S2048 = 8,
}

impl SizeClass {
    /// Get the size for this class.
    #[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,
        }
    }

    /// Get the alignment for this class.
    #[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,
        }
    }

    /// Get the layout for this size class.
    #[inline(always)]
    pub const fn layout(self) -> Layout {
        // SAFETY: All size classes have valid size/alignment combinations
        unsafe { Layout::from_size_align_unchecked(self.size(), self.align()) }
    }

    /// Determine the size class for a given size.
    #[inline(always)]
    pub fn for_size(size: usize) -> Option<Self> {
        // Use bit operations for fast classification
        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,
        }
    }

    /// Get all size classes.
    #[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,
        ]
    }
}

/// Pre-computed layouts for common types.
pub mod common {
    use super::*;

    /// Layout for u64.
    pub const U64: Layout = Layout::new::<u64>();
    
    /// Layout for usize.
    pub const USIZE: Layout = Layout::new::<usize>();
    
    /// Layout for f64.
    pub const F64: Layout = Layout::new::<f64>();
    
    /// Layout for f32.
    pub const F32: Layout = Layout::new::<f32>();
    
    /// Layout for [u8; 16].
    pub const U8X16: Layout = Layout::new::<[u8; 16]>();
    
    /// Layout for [u32; 4].
    pub const U32X4: Layout = Layout::new::<[u32; 4]>();
    
    /// Layout for [f32; 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);
        }
    }
}