//! Bounded block bitmap ownership with permanently reserved metadata blocks. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Error { BadCapacity, BadReserved, BadBitmap, ReservedFree, NoSpace, OutOfBounds, ReservedBlock, AlreadyFree, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Counts { pub reserved: u32, pub user: u32, pub free: u32, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Bitmap { capacity: u8, reserved: u64, allocated: u64, } impl Bitmap { pub fn validate(capacity: u8, reserved: u64, allocated: u64) -> Result { if capacity == 0 || capacity > 64 { return Err(Error::BadCapacity); } let valid = if capacity == 64 { u64::MAX } else { (1u64 << capacity) - 1 }; if reserved & !valid != 0 { return Err(Error::BadReserved); } if allocated & !valid != 0 { return Err(Error::BadBitmap); } if allocated & reserved != reserved { return Err(Error::ReservedFree); } Ok(Self {capacity, reserved, allocated}) } pub const fn allocated_bits(&self) -> u64 { self.allocated } pub fn counts(&self) -> Counts { let reserved = self.reserved.count_ones(); let user = (self.allocated & !self.reserved).count_ones(); Counts {reserved, user, free: u32::from(self.capacity) - reserved - user} } pub fn allocate(&mut self) -> Result { for block in 0..self.capacity { let bit = 1u64 << block; if self.allocated & bit == 0 { self.allocated |= bit; return Ok(block); } } Err(Error::NoSpace) } pub fn release(&mut self, block: u8) -> Result<(), Error> { if block >= self.capacity { return Err(Error::OutOfBounds); } let bit = 1u64 << block; if self.reserved & bit != 0 { return Err(Error::ReservedBlock); } if self.allocated & bit == 0 { return Err(Error::AlreadyFree); } self.allocated &= !bit; Ok(()) } }