use core::ops::Bound;
use crate::{
bintree::{NodesCmp, NodesCmpKey},
node_data::{NodesDataLend, NodesDataLendGat},
};
use super::*;
mod iter;
mod validate_error {
#[derive(thiserror::Error, Debug)]
pub enum OpaqueError<Index: core::fmt::Debug> {
#[error(transparent)]
BinaryTree(crate::bintree::accessor::validate_error::OpaqueError<Index>),
#[error("red node {0:?} has a red child {1:?}")]
RedNodeHasRedChild(Index, Index),
#[error("black height mismatch at node {0:?}: left = {1}, right = {2}")]
BlackHeightMismatch(Index, usize, usize),
}
}
impl<Index> Tree<Index> {
#[inline]
pub fn read<Nodes>(&self, nodes: Nodes) -> TreeAccessor<'_, Nodes, Index>
where
Nodes: NodesRb<Index>,
{
TreeAccessor {
raw: self.raw.read(nodes),
}
}
}
#[derive(Debug)]
pub struct TreeAccessor<'head, Nodes, Index> {
raw: crate::bintree::accessor::TreeAccessor<'head, Nodes, Index>,
}
impl<'tree, Nodes, Index> Clone for TreeAccessor<'tree, Nodes, Index>
where
Nodes: Clone,
{
#[inline]
fn clone(&self) -> Self {
TreeAccessor {
raw: self.raw.clone(),
}
}
}
impl<'tree, Nodes, Index> Copy for TreeAccessor<'tree, Nodes, Index> where Nodes: Copy {}
impl<'tree, Nodes, Index> TreeAccessor<'tree, Nodes, Index>
where
Nodes: NodesRb<Index>,
Index: PartialEq + Clone,
{
#[inline]
pub fn nodes(&self) -> &Nodes {
self.raw.nodes()
}
#[inline]
pub fn nodes_mut(&mut self) -> &mut Nodes {
self.raw.nodes_mut()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.raw.is_empty()
}
#[inline]
pub fn front_index(&self) -> Option<Index> {
self.raw.front_index()
}
#[inline]
pub fn back_index(&self) -> Option<Index> {
self.raw.back_index()
}
#[doc(alias = "first")]
#[inline]
pub fn front(&self) -> Option<<Nodes as NodesDataLendGat<'_, Index>>::Data>
where
Nodes: NodesDataLend<Index>,
{
self.raw.front()
}
#[doc(alias = "last")]
#[inline]
pub fn back(&self) -> Option<<Nodes as NodesDataLendGat<'_, Index>>::Data>
where
Nodes: NodesDataLend<Index>,
{
self.raw.back()
}
#[inline]
pub fn next_index(&self, node: Index) -> Option<Index> {
self.raw.next_index(node)
}
#[inline]
pub fn prev_index(&self, node: Index) -> Option<Index> {
self.raw.prev_index(node)
}
#[track_caller]
pub fn validate(&self) -> Result<(), validate_error::OpaqueError<Index>>
where
Index: core::fmt::Debug,
{
use validate_error::OpaqueError as Error;
self.raw.validate().map_err(Error::BinaryTree)?;
let Some(root) = self.raw.tree().root.clone() else {
return Ok(());
};
self.validate_inner(root)?;
Ok(())
}
fn validate_inner(&self, node: Index) -> Result<usize, validate_error::OpaqueError<Index>>
where
Index: core::fmt::Debug,
{
use validate_error::OpaqueError as Error;
let color = self.nodes().node_color(node.clone());
let left = self.nodes().node_left(node.clone());
let right = self.nodes().node_right(node.clone());
if color == Color::Red {
if let Some(child) = &left
&& self.nodes().node_color(child.clone()) == Color::Red
{
return Err(Error::RedNodeHasRedChild(node, child.clone()));
}
if let Some(child) = &right
&& self.nodes().node_color(child.clone()) == Color::Red
{
return Err(Error::RedNodeHasRedChild(node, child.clone()));
}
}
let left_black_height = match left {
Some(child) => self.validate_inner(child)?,
None => 0,
};
let right_black_height = match right {
Some(child) => self.validate_inner(child)?,
None => 0,
};
if left_black_height != right_black_height {
return Err(Error::BlackHeightMismatch(
node,
left_black_height,
right_black_height,
));
}
Ok(left_black_height + (color == Color::Black) as usize)
}
}
impl<'tree, Nodes, Index> TreeAccessor<'tree, Nodes, Index>
where
Nodes: NodesRb<Index>,
Index: PartialEq + Clone,
{
pub fn bst_find_index<Key>(&self, key: &Key) -> Option<Index>
where
Nodes: NodesCmpKey<Index, Key>,
{
self.raw.bst_find_index(key)
}
#[inline]
pub fn bst_lower_bound<Key>(&self, bound: Bound<&Key>) -> Option<Index>
where
Nodes: NodesCmpKey<Index, Key>,
{
self.raw.bst_lower_bound(bound)
}
#[inline]
pub fn bst_upper_bound<Key>(&self, bound: Bound<&Key>) -> Option<Index>
where
Nodes: NodesCmpKey<Index, Key>,
{
self.raw.bst_upper_bound(bound)
}
}
impl<'tree, Nodes, Index> TreeAccessor<'tree, Nodes, Index>
where
Nodes: NodesRb<Index>,
Index: PartialEq + Clone,
{
pub fn bst_validate<Data>(
&self,
map_data: impl FnMut(&Nodes, Index) -> Data,
) -> Result<(), crate::bintree::accessor::validate_error::BstOpaqueError<Index, Data>>
where
Nodes: NodesCmp<Index>,
Index: core::fmt::Debug,
Data: core::fmt::Debug,
{
self.raw.bst_validate(map_data)
}
}