use std::mem::MaybeUninit;
use crate::bit_vec::BitVec;
pub(crate) struct DelVec<T> {
size: usize,
deleted: BitVec,
data: Box<[MaybeUninit<T>]>,
}
unsafe fn assume_init<T>(r: &MaybeUninit<T>) -> &T {
&*(r as *const MaybeUninit<T> as *const T)
}
unsafe fn assume_init_mut<T>(r: &mut MaybeUninit<T>) -> &mut T {
&mut *(r as *mut MaybeUninit<T> as *mut T)
}
impl<T> DelVec<T> {
pub(crate) fn new(vals: Vec<T>) -> Self {
Self {
size: vals.len(),
deleted: BitVec::new(vals.len()),
data: unsafe {
let vals = vals.into_boxed_slice();
Box::from_raw(Box::into_raw(vals) as *mut [MaybeUninit<T>])
},
}
}
pub(crate) fn len(&self) -> usize {
self.size
}
pub(crate) fn capacity(&self) -> usize {
self.data.len()
}
pub(crate) fn get(&self, idx: usize) -> Option<&T> {
if idx >= self.data.len() || self.deleted.get(idx) {
return None;
}
unsafe { Some(assume_init(self.data.get_unchecked(idx))) }
}
pub(crate) fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
if idx >= self.data.len() || self.deleted.get(idx) {
return None;
}
unsafe { Some(assume_init_mut(self.data.get_unchecked_mut(idx))) }
}
pub(crate) fn take(&mut self, idx: usize) -> Option<T> {
if idx >= self.data.len() || self.deleted.get(idx) {
return None;
}
self.deleted.set(idx);
self.size -= 1;
unsafe { Some(std::ptr::read(assume_init(self.data.get_unchecked(idx)))) }
}
pub(crate) fn delete(&mut self, idx: usize) -> bool {
if idx >= self.data.len() || self.deleted.get(idx) {
return false;
}
self.deleted.set(idx);
self.size -= 1;
unsafe {
let ptr: *mut T = self.data.as_mut_ptr().add(idx).cast();
std::ptr::drop_in_place(ptr);
}
true
}
}
impl<T> Drop for DelVec<T> {
fn drop(&mut self) {
for i in 0..self.data.len() {
if !self.deleted.get(i) {
unsafe {
let ptr: *mut T = self.data.as_mut_ptr().add(i).cast();
std::ptr::drop_in_place(ptr);
}
}
}
}
}