use core::marker::PhantomData;
use smallvec::SmallVec;
use crate::borrow::{DestroyableMutRef, DestroyableRef, DormantMutRef};
use crate::entry::{ItemEntry, NodeMaybeMut, XEntry};
use crate::mark::{NoneMark, XMark};
use crate::node::XNode;
use crate::xarray::{XArray, MAX_HEIGHT, SLOT_SIZE};
trait Operation {}
struct ReadOnly {}
struct ReadWrite {}
impl Operation for ReadOnly {}
impl Operation for ReadWrite {}
enum CursorState<'a, I, O>
where
I: ItemEntry,
O: Operation,
{
Inactive(PhantomData<O>),
AtNode {
node: DestroyableRef<'a, XNode<I>>,
operation_offset: u8,
},
AtNodeMut {
node: DestroyableMutRef<'a, XNode<I>>,
operation_offset: u8,
},
}
impl<'a, I: ItemEntry, O: Operation> Default for CursorState<'a, I, O> {
fn default() -> Self {
Self::Inactive(PhantomData)
}
}
impl<'a, I: ItemEntry, O: Operation> CursorState<'a, I, O> {
fn move_to(&mut self, node: &'a XNode<I>, index: u64) {
let operation_offset = node.entry_offset(index);
*self = Self::AtNode {
node: DestroyableRef::new(node),
operation_offset,
};
}
}
impl<'a, I: ItemEntry> CursorState<'a, I, ReadWrite> {
fn move_to_mut(&mut self, node: &'a mut XNode<I>, index: u64) {
let operation_offset = node.entry_offset(index);
*self = Self::AtNodeMut {
node: DestroyableMutRef::new(node),
operation_offset,
};
}
fn move_to_maybe_mut(&mut self, node: NodeMaybeMut<'a, I>, index: u64) {
match node {
NodeMaybeMut::Shared(node) => self.move_to(node, index),
NodeMaybeMut::Exclusive(node) => self.move_to_mut(node, index),
}
}
}
impl<'a, I: ItemEntry, O: Operation> CursorState<'a, I, O> {
fn into_node(self) -> Option<(&'a XNode<I>, u8)> {
match self {
Self::AtNode {
node,
operation_offset,
} => Some((node.borrow(), operation_offset)),
Self::AtNodeMut {
node,
operation_offset,
} => Some((node.into(), operation_offset)),
Self::Inactive(..) => None,
}
}
}
impl<'a, I: ItemEntry> CursorState<'a, I, ReadWrite> {
fn into_node_mut(self) -> Option<(&'a mut XNode<I>, u8)> {
match self {
Self::AtNodeMut {
node,
operation_offset,
} => Some((node.into(), operation_offset)),
Self::Inactive(..) | Self::AtNode { .. } => None,
}
}
fn into_node_maybe_mut(self) -> Option<(NodeMaybeMut<'a, I>, u8)> {
match self {
Self::AtNode {
node,
operation_offset,
} => Some((NodeMaybeMut::Shared(node.borrow()), operation_offset)),
Self::AtNodeMut {
node,
operation_offset,
} => Some((NodeMaybeMut::Exclusive(node.into()), operation_offset)),
Self::Inactive(..) => None,
}
}
}
impl<'a, I: ItemEntry> CursorState<'a, I, ReadOnly> {
fn as_node(&self) -> Option<(&'a XNode<I>, u8)> {
match self {
Self::AtNode {
node,
operation_offset,
} => Some((node.borrow(), *operation_offset)),
Self::Inactive(..) | Self::AtNodeMut { .. } => None,
}
}
}
impl<'a, I: ItemEntry> CursorState<'a, I, ReadWrite> {
fn as_node(&self) -> Option<(&XNode<I>, u8)> {
match self {
Self::AtNode {
node,
operation_offset,
} => Some((node.borrow(), *operation_offset)),
Self::AtNodeMut {
node,
operation_offset,
} => Some((node.borrow(), *operation_offset)),
Self::Inactive(..) => None,
}
}
fn as_node_mut(&mut self) -> Option<(&mut XNode<I>, u8)> {
match self {
Self::AtNodeMut {
node,
operation_offset,
} => Some((node.borrow_mut(), *operation_offset)),
Self::Inactive(..) | Self::AtNode { .. } => None,
}
}
}
impl<'a, I: ItemEntry, O: Operation> CursorState<'a, I, O> {
fn is_at_node(&self) -> bool {
match self {
Self::AtNode { .. } | Self::AtNodeMut { .. } => true,
Self::Inactive(..) => false,
}
}
fn is_leaf(&self) -> bool {
match self {
Self::AtNodeMut { node, .. } => node.borrow().is_leaf(),
Self::AtNode { node, .. } => node.borrow().is_leaf(),
Self::Inactive(..) => false,
}
}
}
impl<'a, I: ItemEntry> CursorState<'a, I, ReadWrite> {
fn is_at_node_mut(&self) -> bool {
match self {
Self::AtNodeMut { .. } => true,
Self::Inactive(..) | Self::AtNode { .. } => false,
}
}
}
pub struct Cursor<'a, I, M = NoneMark>
where
I: ItemEntry,
M: Into<XMark>,
{
xa: &'a XArray<I, M>,
index: u64,
state: CursorState<'a, I, ReadOnly>,
ancestors: SmallVec<[&'a XNode<I>; MAX_HEIGHT]>,
}
impl<'a, I: ItemEntry, M: Into<XMark>> Cursor<'a, I, M> {
pub(super) fn new(xa: &'a XArray<I, M>, index: u64) -> Self {
let mut cursor = Self {
xa,
index,
state: CursorState::default(),
ancestors: SmallVec::new(),
};
cursor.traverse_to_target();
cursor
}
pub fn reset_to(&mut self, index: u64) {
self.reset();
self.index = index;
self.traverse_to_target();
}
pub fn index(&self) -> u64 {
self.index
}
pub fn next(&mut self) {
self.index = self.index.checked_add(1).unwrap();
if !self.state.is_at_node() {
return;
}
let (mut current_node, mut operation_offset) =
core::mem::take(&mut self.state).into_node().unwrap();
operation_offset += 1;
while operation_offset == SLOT_SIZE as u8 {
let Some(parent_node) = self.ancestors.pop() else {
self.reset();
return;
};
operation_offset = current_node.offset_in_parent() + 1;
current_node = parent_node;
}
self.state.move_to(current_node, self.index);
self.continue_traverse_to_target();
}
pub fn load(&mut self) -> Option<I::Ref<'a>> {
self.traverse_to_target();
self.state
.as_node()
.and_then(|(node, off)| node.entry(off).as_item_ref())
}
pub fn is_marked(&mut self, mark: M) -> bool {
self.traverse_to_target();
self.state
.as_node()
.map(|(node, off)| node.is_marked(off, mark.into().index()))
.unwrap_or(false)
}
fn traverse_to_target(&mut self) {
if self.state.is_at_node() {
return;
}
let max_index = self.xa.max_index();
if max_index < self.index || max_index == 0 {
return;
}
let current_node = self.xa.head().as_node_ref().unwrap();
self.state.move_to(current_node, self.index);
self.continue_traverse_to_target();
}
fn continue_traverse_to_target(&mut self) {
while !self.state.is_leaf() {
let (current_node, operation_offset) =
core::mem::take(&mut self.state).into_node().unwrap();
let operated_entry = current_node.entry(operation_offset);
if !operated_entry.is_node() {
self.reset();
return;
}
self.ancestors.push(current_node);
let new_node = operated_entry.as_node_ref().unwrap();
self.state.move_to(new_node, self.index);
}
}
fn reset(&mut self) {
self.state = CursorState::default();
self.ancestors.clear();
}
}
struct NodeMutRef<'a, I>
where
I: ItemEntry,
{
inner: DormantMutRef<'a, XNode<I>>,
}
impl<'a, I: ItemEntry> NodeMutRef<'a, I> {
fn new(node: &'a mut XNode<I>, operation_offset: u8) -> (&'a mut XEntry<I>, NodeMutRef<'a, I>) {
let (node, inner) = DormantMutRef::new(node);
(node.entry_mut(operation_offset), NodeMutRef { inner })
}
unsafe fn awaken(self) -> &'a mut XNode<I> {
unsafe { self.inner.awaken() }
}
unsafe fn awaken_modified(self, last_index: u64) -> (&'a mut XNode<I>, bool) {
let node = unsafe { self.inner.awaken() };
let changed = node.update_mark(node.height().height_offset(last_index));
(node, changed)
}
}
pub struct CursorMut<'a, I, M = NoneMark>
where
I: ItemEntry,
M: Into<XMark>,
{
xa: DormantMutRef<'a, XArray<I, M>>,
index: u64,
state: CursorState<'a, I, ReadWrite>,
mut_ancestors: SmallVec<[NodeMutRef<'a, I>; MAX_HEIGHT]>,
ancestors: SmallVec<[&'a XNode<I>; MAX_HEIGHT]>,
}
impl<'a, I: ItemEntry, M: Into<XMark>> CursorMut<'a, I, M> {
pub(super) fn new(xa: &'a mut XArray<I, M>, index: u64) -> Self {
let mut cursor = Self {
xa: DormantMutRef::new(xa).1,
index,
state: CursorState::default(),
mut_ancestors: SmallVec::new(),
ancestors: SmallVec::new(),
};
cursor.traverse_to_target();
cursor
}
pub fn reset_to(&mut self, index: u64) {
self.reset();
self.index = index;
self.traverse_to_target();
}
pub fn index(&self) -> u64 {
self.index
}
pub fn next(&mut self) {
self.index = self.index.checked_add(1).unwrap();
if !self.state.is_at_node() {
return;
}
let (mut current_node, mut operation_offset) = core::mem::take(&mut self.state)
.into_node_maybe_mut()
.unwrap();
operation_offset += 1;
while operation_offset == SLOT_SIZE as u8 {
let offset_in_parent = current_node.offset_in_parent();
drop(current_node);
let parent_node = if let Some(node) = self.ancestors.pop() {
NodeMaybeMut::Shared(node)
} else if let Some(node) = self.mut_ancestors.pop() {
NodeMaybeMut::Exclusive(unsafe { node.awaken_modified(self.index - 1).0 })
} else {
self.reset();
return;
};
operation_offset = offset_in_parent + 1;
current_node = parent_node;
}
self.state.move_to_maybe_mut(current_node, self.index);
self.continue_traverse_to_target();
}
pub fn load(&mut self) -> Option<I::Ref<'_>> {
self.traverse_to_target();
self.state
.as_node()
.and_then(|(node, off)| node.entry(off).as_item_ref())
}
pub fn is_marked(&mut self, mark: M) -> bool {
self.traverse_to_target();
self.state
.as_node()
.map(|(node, off)| node.is_marked(off, mark.into().index()))
.unwrap_or(false)
}
pub fn store(&mut self, item: I) -> Option<I> {
self.expand_and_traverse_to_target();
self.state
.as_node_mut()
.and_then(|(node, off)| node.set_entry(off, XEntry::from_item(item)).into_item())
}
pub fn remove(&mut self) -> Option<I> {
self.ensure_exclusive_before_modification();
self.state
.as_node_mut()
.and_then(|(node, off)| node.set_entry(off, XEntry::EMPTY).into_item())
}
pub fn set_mark(&mut self, mark: M) -> Result<(), ()> {
self.ensure_exclusive_before_modification();
self.state
.as_node_mut()
.filter(|(node, off)| node.entry(*off).is_item())
.map(|(node, off)| node.set_mark(off, mark.into().index()))
.ok_or(())
}
pub fn unset_mark(&mut self, mark: M) -> Result<(), ()> {
self.ensure_exclusive_before_modification();
self.state
.as_node_mut()
.filter(|(node, off)| node.entry(*off).is_item())
.map(|(node, off)| node.unset_mark(off, mark.into().index()))
.ok_or(())
}
fn traverse_to_target(&mut self) {
if self.state.is_at_node() {
return;
}
let xa = unsafe { self.xa.reborrow() };
let max_index = xa.max_index();
if max_index < self.index || max_index == 0 {
return;
}
let current_node = xa.head_mut().as_node_maybe_mut().unwrap();
self.state.move_to_maybe_mut(current_node, self.index);
self.continue_traverse_to_target();
}
fn expand_and_traverse_to_target(&mut self) {
if self.state.is_at_node() {
self.ensure_exclusive_before_modification();
return;
}
let head = {
let xa = unsafe { self.xa.reborrow() };
xa.reserve(self.index);
xa.head_mut().as_node_mut_or_cow().unwrap()
};
self.state.move_to_mut(head, self.index);
self.exclusively_traverse_to_target();
}
fn ensure_exclusive_before_modification(&mut self) {
if self.state.is_at_node_mut() {
return;
}
self.state = CursorState::default();
self.ancestors.clear();
let node = match self.mut_ancestors.pop() {
Some(node) => unsafe { node.awaken() },
None => {
let xa = unsafe { self.xa.reborrow() };
let head = xa.head_mut();
if !head.is_node() {
return;
}
head.as_node_mut_or_cow().unwrap()
}
};
self.state.move_to_mut(node, self.index);
self.exclusively_traverse_to_target();
}
fn continue_traverse_to_target(&mut self) {
while !self.state.is_leaf() {
let (current_node, operation_offset) = core::mem::take(&mut self.state)
.into_node_maybe_mut()
.unwrap();
let next_node = match current_node {
NodeMaybeMut::Shared(node) => {
let operated_entry = node.entry(operation_offset);
if !operated_entry.is_node() {
self.reset();
return;
}
self.ancestors.push(node);
NodeMaybeMut::Shared(operated_entry.as_node_ref().unwrap())
}
NodeMaybeMut::Exclusive(node) => {
let (operated_entry, dormant_node) = NodeMutRef::new(node, operation_offset);
if !operated_entry.is_node() {
self.reset();
return;
}
self.mut_ancestors.push(dormant_node);
operated_entry.as_node_maybe_mut().unwrap()
}
};
self.state.move_to_maybe_mut(next_node, self.index);
}
}
fn exclusively_traverse_to_target(&mut self) {
while !self.state.is_leaf() {
let (current_node, operation_offset) =
core::mem::take(&mut self.state).into_node_mut().unwrap();
if current_node.entry(operation_offset).is_null() {
let new_node = XNode::new(current_node.height().go_leaf(), operation_offset);
let new_entry = XEntry::from_node(new_node);
current_node.set_entry(operation_offset, new_entry);
}
let (operated_entry, dormant_node) = NodeMutRef::new(current_node, operation_offset);
self.mut_ancestors.push(dormant_node);
let next_node = operated_entry.as_node_mut_or_cow().unwrap();
self.state.move_to_mut(next_node, self.index)
}
}
fn reset(&mut self) {
self.state = CursorState::default();
self.ancestors.clear();
while let Some(node) = self.mut_ancestors.pop() {
let (_, changed) = unsafe { node.awaken_modified(self.index) };
if !changed {
self.mut_ancestors.clear();
break;
}
}
}
}
impl<'a, I: ItemEntry, M: Into<XMark>> Drop for CursorMut<'a, I, M> {
fn drop(&mut self) {
self.reset();
}
}