use std::{mem, ptr};
use crate::{
alloc,
depot::{heap, index::Position},
};
pub(in crate::depot) unsafe trait Store: Sized {
type Key: crate::depot::raw::Address;
type Priority: Ord;
type Position: Position;
type Storage: alloc::raw::Shape<Root = heap::Stored<Self::Key, Self::Priority>, Tail = Self::Position>;
type Extra;
fn precedes(left: &Self::Key, right: &Self::Key) -> bool;
fn storage(&self) -> &alloc::raw::Block<Self::Storage, u32, Self::Extra>;
fn storage_mut(&mut self) -> &mut alloc::raw::Block<Self::Storage, u32, Self::Extra>;
fn view(&self) -> View<'_, Self> {
let block = self.storage();
(&block.state, block.as_ref(), block.tail())
}
fn values(&self) -> &[mem::MaybeUninit<heap::Stored<Self::Key, Self::Priority>>] {
let view = self.view();
unsafe { view.1.get_unchecked(..*view.0 as usize) }
}
fn positions(&self) -> &[Self::Position] {
self.view().2
}
fn first(&self) -> Option<&heap::Stored<Self::Key, Self::Priority>> {
Some(unsafe { self.values().first()?.assume_init_ref() })
}
fn peek(&self) -> Option<(Self::Key, &Self::Priority)> {
let entry = self.first()?;
Some((entry.identity, &entry.priority))
}
fn current(&self, index: usize) -> Option<&heap::Stored<Self::Key, Self::Priority>> {
use crate::depot::raw::{Link as _, Word as _};
let position = *self.positions().get(index)?;
if position == Self::Position::NONE {
return None;
}
Some(unsafe {
self.values()
.get_unchecked(position.offset())
.assume_init_ref()
})
}
unsafe fn parts(&mut self) -> Edit<'_, Self> {
self.storage_mut().parts_mut()
}
unsafe fn reindex(map: &mut [Self::Position], key: Self::Key, position: Self::Position) {
use crate::depot::raw::Address as _;
unsafe { *map.get_unchecked_mut(key.index()) = position };
}
unsafe fn destroy(&mut self) {
if mem::needs_drop::<Self::Priority>() {
let (len, entries, _) = self.storage_mut().parts_mut();
let entries = unsafe { entries.get_unchecked_mut(..*len as usize) };
for entry in entries.iter_mut().rev() {
unsafe { entry.assume_init_drop() };
}
}
}
fn clear(&mut self) {
use crate::depot::raw::Link as _;
let (len, entries, map) = unsafe { self.parts() };
while *len != 0 {
*len -= 1;
let entry = unsafe { entries.get_unchecked_mut(*len as usize).assume_init_mut() };
unsafe {
Self::reindex(map, entry.identity, Self::Position::NONE);
ptr::drop_in_place(entry);
}
}
}
}
type View<'a, S> = (
&'a u32,
&'a [mem::MaybeUninit<heap::Stored<<S as Store>::Key, <S as Store>::Priority>>],
&'a [<S as Store>::Position],
);
type Edit<'a, S> = (
&'a mut u32,
&'a mut [mem::MaybeUninit<heap::Stored<<S as Store>::Key, <S as Store>::Priority>>],
&'a mut [<S as Store>::Position],
);