use alloc::collections::VecDeque;
use core::marker::PhantomData;
use crate::cursor::{Cursor, CursorMut};
use crate::entry::{ItemEntry, XEntry};
use crate::mark::{NoneMark, XMark};
use crate::node::{Height, XNode};
use crate::range::Range;
pub(super) const BITS_PER_LAYER: usize = 6;
pub(super) const SLOT_SIZE: usize = 1 << BITS_PER_LAYER;
pub(super) const SLOT_MASK: usize = SLOT_SIZE - 1;
pub(super) const MAX_HEIGHT: usize = 64 / BITS_PER_LAYER + 1;
pub struct XArray<I, M = NoneMark>
where
I: ItemEntry,
M: Into<XMark>,
{
marks: [bool; 3],
head: XEntry<I>,
_marker: PhantomData<M>,
}
impl<I: ItemEntry, M: Into<XMark>> XArray<I, M> {
pub const fn new() -> Self {
Self {
marks: [false; 3],
head: XEntry::EMPTY,
_marker: PhantomData,
}
}
pub fn set_mark(&mut self, mark: M) {
self.marks[mark.into().index()] = true;
}
pub fn unset_mark(&mut self, mark: M) {
self.marks[mark.into().index()] = false;
}
pub fn is_marked(&self, mark: M) -> bool {
self.marks[mark.into().index()]
}
pub(super) fn head(&self) -> &XEntry<I> {
&self.head
}
pub(super) fn head_mut(&mut self) -> &mut XEntry<I> {
&mut self.head
}
pub(super) fn reserve(&mut self, index: u64) {
if self.head.is_null() {
let height = Height::from_index(index);
self.head = XEntry::from_node(XNode::new_root(height));
return;
}
loop {
let height = self.head.as_node_ref().unwrap().height();
if height.max_index() >= index {
return;
}
let old_entry = core::mem::replace(&mut self.head, XEntry::EMPTY);
let mut new_node = XNode::new_root(height.go_root());
new_node.set_entry(0, old_entry);
self.head = XEntry::from_node(new_node);
}
}
pub(super) fn max_index(&self) -> u64 {
self.head()
.as_node_ref()
.map(|node| node.height().max_index())
.unwrap_or(0)
}
pub fn load(&self, index: u64) -> Option<I::Ref<'_>> {
let mut cursor = self.cursor(index);
cursor.load()
}
pub fn store(&mut self, index: u64, item: I) -> Option<I> {
let mut cursor = self.cursor_mut(index);
cursor.store(item)
}
pub fn unset_mark_all(&mut self, mark: M) {
let mut pending_nodes = VecDeque::new();
if let Some(node) = self.head.as_node_mut_or_cow() {
pending_nodes.push_back(node);
}
let mark_index = mark.into().index();
while let Some(node) = pending_nodes.pop_front() {
let node_mark = node.mark(mark_index);
node.clear_mark(mark_index);
node.entries_mut()
.iter_mut()
.enumerate()
.filter(|(offset, _)| node_mark.is_marked(*offset as u8))
.filter_map(|(_, next_entry)| next_entry.as_node_mut_or_cow())
.for_each(|next_node| pending_nodes.push_back(next_node));
}
}
pub fn remove(&mut self, index: u64) -> Option<I> {
let mut cursor = self.cursor_mut(index);
cursor.remove()
}
pub fn cursor(&self, index: u64) -> Cursor<'_, I, M> {
Cursor::new(self, index)
}
pub fn cursor_mut(&mut self, index: u64) -> CursorMut<'_, I, M> {
CursorMut::new(self, index)
}
pub fn range(&self, range: core::ops::Range<u64>) -> Range<'_, I, M> {
let cursor = Cursor::new(self, range.start);
Range::new(cursor, range.end)
}
}
impl<I: ItemEntry + Clone, M: Into<XMark>> Clone for XArray<I, M> {
fn clone(&self) -> Self {
let cloned_head = self.head.clone();
Self {
marks: self.marks,
head: cloned_head,
_marker: PhantomData,
}
}
}