use std::ops::{Deref, DerefMut};
use crate::{
ConstDefault, ordering::Ordering, Position, RawHeap, raw_heap,
indexable_vec::IndexableVec,
};
pub use crate::indexable_vec::{Idx, Iter};
#[derive(Clone)]
pub struct IndexableHeap<T, O> {
data: IndexableVec<T>,
ord: O,
}
impl<T, O: Default> Default for IndexableHeap<T, O> {
fn default() -> Self {
Self { data: Default::default(), ord: Default::default() }
}
}
impl<T, O> IndexableHeap<T, O> {
pub const fn new() -> Self
where
O: ConstDefault,
{
Self {
data: IndexableVec::new(),
ord: O::DEFAULT,
}
}
pub fn with_capacity(capacity: usize) -> Self
where
O: Default,
{
Self {
data: IndexableVec::with_capacity(capacity),
ord: O::default(),
}
}
pub const fn with_ordering(ord: O) -> Self {
Self {
data: IndexableVec::new(),
ord,
}
}
pub fn with_capacity_and_ordering(capacity: usize, ord: O) -> Self {
Self {
data: IndexableVec::with_capacity(capacity),
ord,
}
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn capacity(&self) -> usize {
self.data.capacity()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
impl<T, O: Ordering<T>> IndexableHeap<T, O> {
pub fn peek(&self) -> Option<&T> {
self.data.peek()
}
pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T, O>> {
RawHeap::peek_mut(&mut self.data).map(|raw| PeekMut {
raw,
ord: &self.ord,
})
}
pub fn by_index(&self, index: Idx<T>) -> &T {
let pos = self.data.index_to_pos(index);
self.data.get(pos)
}
pub fn by_index_mut(&mut self, index: Idx<T>) -> GetMut<'_, T, O> {
let pos = self.data.index_to_pos(index);
GetMut::new(self, pos)
}
pub fn push(&mut self, item: T) -> Idx<T> {
let pos = self.data.len();
let index = self.data.push(item);
self.data.sift_up(pos, &self.ord);
index
}
pub fn pop(&mut self) -> Option<T> {
let item = self.data.pop()?;
Some(self.data.pop_swap(item, &self.ord))
}
pub fn reserve(&mut self, additional: usize) {
self.data.reserve(additional);
}
pub fn reserve_exact(&mut self, additional: usize) {
self.data.reserve_exact(additional);
}
pub fn shrink_to_fit(&mut self) {
self.data.shrink_to_fit();
}
pub fn shrink_to(&mut self, min_capacity: usize) {
self.data.shrink_to(min_capacity);
}
pub fn iter(&self) -> Iter<'_, T> {
self.data.iter()
}
}
pub struct PeekMut<'a, T, O: Ordering<T>> {
raw: raw_heap::PeekMut<'a, IndexableVec<T>>,
ord: &'a O,
}
impl<'a, T, O: Ordering<T>> Drop for PeekMut<'a, T, O> {
fn drop(&mut self) {
self.restore();
}
}
impl<'a, T, O: Ordering<T>> Deref for PeekMut<'a, T, O> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.raw.as_ref()
}
}
impl<'a, T, O: Ordering<T>> DerefMut for PeekMut<'a, T, O> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.raw.as_mut()
}
}
impl<'a, T, O: Ordering<T>> PeekMut<'a, T, O> {
fn restore(&mut self) {
self.raw.restore(self.ord);
}
pub fn index(&self) -> Idx<T> {
self.raw.heap_incoherent().pos_to_index(self.raw.pos())
}
pub fn pop(mut self) -> T {
self.raw.ignore_mutation();
let heap = self.raw.heap_mut();
let item = heap.pop().unwrap();
heap.pop_swap(item, self.ord)
}
}
pub struct GetMut<'a, T, O: Ordering<T>> {
heap: &'a mut IndexableHeap<T, O>,
pos: Position,
sift: bool,
}
impl<'a, T, O: Ordering<T>> Deref for GetMut<'a, T, O> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<'a, T, O: Ordering<T>> DerefMut for GetMut<'a, T, O> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
impl<'a, T, O: Ordering<T>> Drop for GetMut<'a, T, O> {
fn drop(&mut self) {
self.restore();
}
}
impl<'a, T, O: Ordering<T>> GetMut<'a, T, O> {
fn new(heap: &'a mut IndexableHeap<T, O>, pos: Position) -> Self {
assert!(pos < heap.data.len());
Self {
heap,
pos,
sift: false,
}
}
fn pos(&self) -> Position {
if self.pos >= self.heap.data.len() {
unsafe {
std::hint::unreachable_unchecked();
}
}
self.pos
}
pub fn index(&self) -> Idx<T> {
self.heap.data.pos_to_index(self.pos())
}
fn as_ref(&self) -> &T {
self.heap.data.get(self.pos())
}
fn as_mut(&mut self) -> &mut T {
self.sift = true;
self.heap.data.get_mut(self.pos())
}
fn restore(&mut self) -> bool {
if self.sift {
self.sift = false;
self.heap.data.fixup_sift(self.pos(), &self.heap.ord) != self.pos()
} else {
false
}
}
pub fn remove(mut self) -> T {
self.sift = false;
let pos = self.pos();
let item = self.heap.data.swap_remove(pos);
if pos < self.heap.data.len() {
self.heap.data.fixup_sift_to_bottom(pos, &self.heap.ord);
}
item
}
}