use crate::BitBlock;
use crate::primitive::Primitive;
pub trait IBlock: Sized + Default{
type Mask: BitBlock;
fn mask(&self) -> &Self::Mask;
unsafe fn mask_mut(&mut self) -> &mut Self::Mask;
type Item: Primitive;
unsafe fn get_or_zero(&self, index: usize) -> Self::Item;
unsafe fn get_or_insert(
&mut self,
index: usize,
f: impl FnMut() -> Self::Item
) -> Self::Item;
unsafe fn insert_unchecked(
&mut self,
index: usize,
item : Self::Item
);
unsafe fn remove_unchecked(&mut self, index: usize);
#[inline]
fn is_empty(&self) -> bool {
Self::Mask::is_zero(self.mask())
}
}
#[derive(Clone)]
pub struct Level<Block: IBlock>{
blocks: Vec<Block>,
root_empty_block: u64,
}
impl<Block: IBlock> Default for Level<Block> {
#[inline]
fn default() -> Self {
unsafe{ Self::from_blocks_unchecked(vec![Default::default()]) }
}
}
impl<Block: IBlock> Level<Block> {
#[inline]
pub unsafe fn from_blocks_unchecked(blocks: Vec<Block>) -> Self {
Self{blocks, root_empty_block: u64::MAX}
}
#[inline]
pub fn blocks(&self) -> &[Block] {
self.blocks.as_slice()
}
#[inline]
pub fn blocks_mut(&mut self) -> &mut [Block] {
self.blocks.as_mut_slice()
}
#[inline]
unsafe fn next_empty_block_index(block: &mut Block) -> &mut u64 {
block.mask_mut().as_array_mut().get_unchecked_mut(0)
}
#[inline]
fn pop_empty_block(&mut self) -> Option<usize> {
if self.root_empty_block == u64::MAX {
return None;
}
let index = self.root_empty_block as usize;
unsafe{
let empty_block = self.blocks.get_unchecked_mut(index);
let next_empty_block_index = Self::next_empty_block_index(empty_block);
self.root_empty_block = *next_empty_block_index;
*next_empty_block_index = 0;
}
Some(index)
}
#[inline]
unsafe fn push_empty_block(&mut self, block_index: usize){
let empty_block = self.blocks.get_unchecked_mut(block_index);
let next_empty_block_index = Self::next_empty_block_index(empty_block);
*next_empty_block_index = self.root_empty_block;
self.root_empty_block = block_index as u64;
}
#[inline]
pub fn insert_block(&mut self) -> usize {
if let Some(index) = self.pop_empty_block(){
index
} else {
let index = self.blocks.len();
self.blocks.push(Default::default());
index
}
}
#[inline]
pub fn push_block(&mut self, block: Block) -> usize {
let index = self.blocks.len();
self.blocks.push(block);
index
}
#[inline]
pub unsafe fn remove_empty_block_unchecked(&mut self, block_index: usize) {
self.push_empty_block(block_index);
}
}