use crate::{UnthBuf, CellLayout, Bits, BITS_PER_CELL};
#[derive(Clone, Copy)]
pub struct AlignedLayout;
impl CellLayout for AlignedLayout {
type Location = AlignedLocation;
#[inline(always)]
fn get_cell_count(capacity: usize, bits: Bits) -> usize {
let elements_per_cell = get_aligned_elements_per_cell(bits.get());
(capacity + elements_per_cell as usize) / elements_per_cell as usize
}
fn get_exact_bit_count(buf: &UnthBuf<Self>) -> usize {
let elements_per_cell = get_aligned_elements_per_cell(buf.bits.get());
buf.data.len()
* elements_per_cell as usize
* buf.bits.get() as usize
}
#[inline(always)]
fn location_of(buf: &UnthBuf<Self>, index: usize) -> Self::Location {
let cell = index / (buf.elpc as usize);
let offset = (index % buf.elpc as usize) as u8 * buf.bits.get();
let mask = buf.mask << offset;
AlignedLocation {
cell, offset, mask
}
}
#[inline(always)]
unsafe fn set_unchecked(buf: &mut UnthBuf<Self>, index: usize, value: usize) {
let loc = Self::location_of(buf, index);
let mut cell = *buf.data.get_unchecked(loc.cell);
cell &= !loc.mask; cell |= value << loc.offset;
*buf.data.get_unchecked_mut(loc.cell) = cell;
}
#[inline(always)]
unsafe fn get_unchecked(buf: &UnthBuf<Self>, index: usize) -> usize {
let loc = Self::location_of(buf, index);
(buf.data.get_unchecked(loc.cell) & loc.mask) >> loc.offset
}
}
#[derive(Clone, Copy)]
pub struct AlignedLocation {
pub(crate) cell: usize,
pub(crate) offset: u8,
pub(crate) mask: usize,
}
impl core::fmt::Debug for AlignedLocation {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "[#{} <<{} &{:b}]", self.cell, self.offset, self.mask)
}
}
#[inline(always)]
pub(crate) fn get_aligned_elements_per_cell(bits: u8) -> u8 {
BITS_PER_CELL / bits
}