use std;
use std::marker::PhantomData;
use comprawvec::CompRawVec;
use WORD_SIZE;
pub const VALID_MAX: usize = !0;
#[inline]
fn shl_or_zero(i: usize, shift: u32) -> usize {
if shift >= WORD_SIZE as u32 {
0
} else {
i << shift
}
}
pub struct CompVec<T> {
data: CompRawVec<T>,
}
pub struct Iter<'a, T: 'a> {
vec: &'a CompVec<T>,
masked_valid: usize,
compressed: usize,
}
pub struct IterMut<'a, T: 'a> {
vec: *mut CompVec<T>,
masked_valid: usize,
compressed: usize,
_marker: PhantomData<&'a T>,
}
impl<T> CompVec<T> {
fn compress_index(valid: usize, index: usize) -> (usize, usize) {
let bit = 1usize << index;
let marker = shl_or_zero(bit, 1);
let mask = marker.wrapping_sub(1);
let compressed = (((valid | bit) & mask).count_ones() - 1) as usize;
(bit, compressed)
}
pub fn set(&mut self, index: usize, value: T) -> &mut T {
let valid = self.data.valid();
let (bit, compressed) = Self::compress_index(valid, index);
if valid & bit == 0 {
unsafe { self.data.insert(bit, compressed, value) }
} else {
unsafe { self.data.replace(compressed, value) }
}
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
let valid = self.data.valid();
let (bit, compressed) = Self::compress_index(valid, index);
if valid & bit != 0 {
unsafe { Some(self.data.get_mut(compressed)) }
} else {
None
}
}
pub fn get(&self, index: usize) -> Option<&T> {
let valid = self.data.valid();
let (bit, compressed) = Self::compress_index(valid, index);
if valid & bit != 0 {
unsafe { Some(self.data.get(compressed)) }
} else {
None
}
}
pub fn get_default_mut<F>(&mut self, index: usize, default: F) -> &mut T
where F: Fn() -> T
{
let valid = self.data.valid();
let (bit, compressed) = Self::compress_index(valid, index);
if valid & bit == 0 {
unsafe { self.data.insert(bit, compressed, default()) }
} else {
unsafe { self.data.get_mut(compressed) }
}
}
pub fn remove(&mut self, index: usize) -> Option<T> {
let valid = self.data.valid();
let (bit, compressed) = Self::compress_index(valid, index);
if valid & bit != 0 {
unsafe { Some(self.data.remove(bit, compressed)) }
} else {
None
}
}
pub fn size(&self) -> usize {
self.data.size()
}
pub fn capacity(&self) -> usize {
self.data.capacity()
}
pub fn is_empty(&self) -> bool {
self.data.valid() == 0
}
#[inline]
pub fn next(&self,
masked_valid: usize,
compressed: usize)
-> Option<((usize, usize), (usize, &T))> {
let valid = self.data.valid();
let index = (valid & masked_valid).trailing_zeros();
if index < (WORD_SIZE as u32) {
let mask = shl_or_zero(std::usize::MAX, index + 1);
Some(((mask, compressed + 1),
(index as usize, unsafe { self.data.get(compressed) })))
} else {
None
}
}
#[inline]
pub fn next_mut(&mut self,
masked_valid: usize,
compressed: usize)
-> Option<((usize, usize), (usize, &mut T))> {
let valid = self.data.valid();
let index = (valid & masked_valid).trailing_zeros();
if index < (WORD_SIZE as u32) {
let mask = shl_or_zero(std::usize::MAX, index + 1);
Some(((mask, compressed + 1),
(index as usize, unsafe { self.data.get_mut(compressed) })))
} else {
None
}
}
pub fn iter(&self) -> Iter<T> {
Iter {
vec: self,
masked_valid: VALID_MAX,
compressed: 0,
}
}
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
vec: self,
masked_valid: VALID_MAX,
compressed: 0,
_marker: PhantomData,
}
}
pub fn new() -> CompVec<T> {
CompVec { data: CompRawVec::new() }
}
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = (usize, &'a T);
fn next(&mut self) -> Option<Self::Item> {
if let Some(((masked_valid, compressed), (index, value))) = self.vec
.next(self.masked_valid,
self.compressed) {
self.masked_valid = masked_valid;
self.compressed = compressed;
Some((index, value))
} else {
None
}
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = (usize, &'a mut T);
fn next(&mut self) -> Option<Self::Item> {
let mut vec = unsafe { &mut *self.vec };
if let Some(((masked_valid, compressed), (index, value))) = vec.next_mut(self.masked_valid,
self.compressed) {
self.masked_valid = masked_valid;
self.compressed = compressed;
Some((index, value))
} else {
None
}
}
}