use crate::index::tree::{IndexOrd, PosRef, TreeNodeRef};
use std::fmt::Display;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub(crate) struct TopDepth(pub usize);
impl std::ops::Sub for TopDepth {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
TopDepth(self.0 - rhs.0)
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub(crate) struct BottomDepth(pub usize);
impl std::ops::Add for BottomDepth {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
BottomDepth(self.0 + rhs.0)
}
}
impl std::ops::AddAssign for BottomDepth {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(crate) enum Position {
Last,
First,
Middle,
}
#[derive(Clone)]
pub(crate) struct PathItem<K> {
pos: PosRef<K>,
version: u16,
position: Position,
bottom_depth: Option<BottomDepth>,
}
impl<K: Display> Display for Path<K> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let path_str = self
.path
.iter()
.map(|e| format!("{}", e.pos))
.collect::<Vec<_>>()
.join("/");
write!(f, "/{}/", path_str,)
}
}
impl<K> PathItem<K> {
pub(crate) fn new(pos: PosRef<K>, version: u16, node_len: usize) -> Self {
let position = if pos.pos == 0 {
Position::First
} else if pos.pos + 1 == node_len {
Position::Last
} else {
Position::Middle
};
Self {
pos,
version,
position,
bottom_depth: None,
}
}
pub(crate) fn set_depth(&mut self, depth: BottomDepth) {
self.bottom_depth = Some(depth);
}
pub(crate) fn version(&self) -> u16 {
self.version
}
pub(crate) fn pos_ref(&self) -> &PosRef<K> {
&self.pos
}
pub(crate) fn bottom_depth(&self) -> BottomDepth {
self.bottom_depth.unwrap()
}
pub(crate) fn position(&self) -> Position {
self.position
}
}
#[derive(Clone)]
pub(crate) struct Path<K> {
search_key: K,
path: Vec<PathItem<K>>,
}
impl<K: IndexOrd + Clone> Path<K> {
pub(crate) fn new(search_key: K) -> Self {
Self {
search_key,
path: Vec::new(),
}
}
pub(crate) fn finish(&mut self, p: PosRef<K>, version: u16, node_len: usize, bottom_depth: BottomDepth) {
self.replace_search_key(p.k.clone());
self.path.push(PathItem::new(p, version, node_len));
self.compute_depths_start(bottom_depth);
}
pub(crate) fn push(&mut self, p: PosRef<K>, version: u16, node_len: usize) {
self.path.push(PathItem::new(p, version, node_len))
}
pub(crate) fn pop(&mut self) -> Option<PathItem<K>> {
self.path.pop()
}
pub(crate) fn clear(&mut self) {
self.path.clear();
}
pub(crate) fn len(&self) -> usize {
self.path.len()
}
pub(crate) fn get(&self, from: TopDepth) -> Option<&PathItem<K>> {
self.path.get(from.0)
}
pub(crate) fn compute_depths(&mut self) {
self.compute_depths_start(BottomDepth(0))
}
pub(crate) fn compute_depths_start(&mut self, mut depth: BottomDepth) {
for p in self.path.iter_mut().rev() {
p.set_depth(depth);
depth += BottomDepth(1);
}
}
pub(crate) fn point_same_node(&self, other: &Self) -> bool {
self.last_id() == other.last_id()
}
pub(crate) fn last_bottom_depth(&self) -> Option<BottomDepth> {
self.last().and_then(|e| e.bottom_depth)
}
pub(crate) fn last_pos_ref(&self) -> Option<&PosRef<K>> {
self.last().map(|e| &e.pos)
}
pub(crate) fn last(&self) -> Option<&PathItem<K>> {
self.path.last()
}
pub(crate) fn last_id(&self) -> Option<TreeNodeRef> {
self.last().map(|e| e.pos.node_ref)
}
pub(crate) fn last_position(&self) -> Position {
self.last().map(|e| e.position()).unwrap()
}
pub(crate) fn short_to_depth(&mut self, bottom_depth: BottomDepth) {
while self.last().and_then(|m| m.bottom_depth) != Some(bottom_depth) {
self.path.pop();
}
}
pub(crate) fn is_empty(&self) -> bool {
self.path.is_empty()
}
pub(crate) fn depth(&self) -> TopDepth {
TopDepth(self.path.len() - 1)
}
pub(crate) fn search_key(&self) -> &K {
&self.search_key
}
pub(crate) fn replace_search_key(&mut self, search_key: K) {
self.search_key = search_key;
}
}