use core::{mem::ManuallyDrop, ptr};
pub(super) struct Hole<'a, T: 'a> {
data: &'a mut [T],
elt: ManuallyDrop<T>,
pos: usize,
}
impl<'a, T> Hole<'a, T> {
#[inline]
pub(super) const unsafe fn new(data: &'a mut [T], pos: usize) -> Self {
debug_assert!(pos < data.len());
let elt = unsafe { ptr::read(data.get_unchecked(pos)) };
Hole {
data,
elt: ManuallyDrop::new(elt),
pos,
}
}
#[inline]
pub(super) const fn pos(&self) -> usize {
self.pos
}
#[inline]
pub(super) const fn element(&self) -> &T {
&self.elt
}
#[inline]
pub(super) const fn element_mut(&mut self) -> &mut T {
&mut self.elt
}
#[inline]
pub(super) const unsafe fn get(&self, index: usize) -> &T {
debug_assert!(index != self.pos);
debug_assert!(index < self.data.len());
unsafe { self.data.get_unchecked(index) }
}
#[inline]
pub(super) const unsafe fn get_mut(&mut self, index: usize) -> &mut T {
debug_assert!(index != self.pos);
debug_assert!(index < self.data.len());
unsafe { self.data.get_unchecked_mut(index) }
}
#[inline]
pub(super) const unsafe fn move_to(&mut self, index: usize) {
debug_assert!(index != self.pos);
debug_assert!(index < self.data.len());
unsafe {
let index_ptr: *const _ = self.data.get_unchecked(index);
let hole_ptr = self.data.get_unchecked_mut(self.pos);
ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1);
}
self.pos = index;
}
}
impl<T> const Drop for Hole<'_, T> {
#[inline]
fn drop(&mut self) {
unsafe {
let pos = self.pos;
ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1);
}
}
}