use core::fmt::{self, Debug, Formatter};
use core::mem::ManuallyDrop;
use core::ops::{Deref, DerefMut};
use super::StaticHeap;
pub struct StaticHeapPeekMut<'a, T: 'a + Ord, const N: usize> {
pub(crate) heap: &'a mut StaticHeap<T, N>,
pub(crate) sift: bool,
}
pub(crate) struct StaticHeapHole<'a, T: 'a> {
pub(crate) data: &'a mut [T],
pub(crate) element: ManuallyDrop<T>,
pub(crate) position: usize,
}
impl<'a, T: Ord, const N: usize> StaticHeapPeekMut<'a, T, N> {
#[inline(always)]
pub fn pop(mut this: StaticHeapPeekMut<'a, T, N>) -> T {
let value = this.heap.pop().unwrap();
this.sift = false;
value
}
}
impl<T: Ord + Debug, const N: usize> Debug for StaticHeapPeekMut<'_, T, N> {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
unsafe {
f.debug_tuple("StaticHeapPeekMut")
.field(self.heap.data.get_unchecked(0))
.finish()
}
}
}
impl<T: Ord, const N: usize> Deref for StaticHeapPeekMut<'_, T, N> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
debug_assert!(self.heap.is_not_empty());
unsafe { self.heap.data.get_unchecked(0) }
}
}
impl<T: Ord, const N: usize> DerefMut for StaticHeapPeekMut<'_, T, N> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
debug_assert!(self.heap.is_not_empty());
unsafe { self.heap.data.get_unchecked_mut(0) }
}
}
impl<T: Ord, const N: usize> Drop for StaticHeapPeekMut<'_, T, N> {
#[inline(always)]
fn drop(&mut self) {
if self.sift {
self.heap.sift_down_range(0, self.heap.len());
}
}
}
impl<'a, T> StaticHeapHole<'a, T> {
#[inline(always)]
pub(crate) unsafe fn new(data: &'a mut [T], position: usize) -> Self {
debug_assert!(position < data.len());
let element = data.as_ptr().add(position).read();
StaticHeapHole {
data,
element: ManuallyDrop::new(element),
position,
}
}
#[inline(always)]
pub(crate) const fn pos(&self) -> usize {
self.position
}
#[inline(always)]
pub(crate) fn elt(&self) -> &T {
&self.element
}
#[inline(always)]
pub(crate) unsafe fn get(&self, index: usize) -> &T {
debug_assert!(index != self.position);
debug_assert!(index < self.data.len());
self.data.get_unchecked(index)
}
#[inline]
pub(crate) unsafe fn move_to(&mut self, index: usize) {
debug_assert!(index != self.position);
debug_assert!(index < self.data.len());
let ptr = self.data.as_mut_ptr();
let index_ptr: *const _ = ptr.add(index);
let hole_ptr = ptr.add(self.position);
index_ptr.copy_to_nonoverlapping(hole_ptr, 1);
self.position = index;
}
}
impl<T> Drop for StaticHeapHole<'_, T> {
#[inline(always)]
fn drop(&mut self) {
unsafe {
let position = self.position;
let element_ptr = &*self.element as *const T;
let hole_ptr = self.data.as_mut_ptr().add(position);
element_ptr.copy_to_nonoverlapping(hole_ptr, 1);
}
}
}