use core::fmt::Debug;
use crate::{
storage::{Storage, DefaultStorage},
util::unreachable_debugchecked,
NodeValue,
};
use super::{BinaryTree, Node, NodeData};
#[derive(Debug)]
pub struct NodeRef<'a, B, L, K, S = DefaultStorage<Node<B, L, K>>>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
pub(super) tree: &'a BinaryTree<B, L, K, S>,
pub(super) key: K,
}
impl<'a, B, L, K, S> NodeRef<'a, B, L, K, S>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
pub fn new_raw(tree: &'a BinaryTree<B, L, K, S>, key: K) -> Option<Self> {
if tree.storage.contains_key(&key) {
Some(unsafe {
Self::new_raw_unchecked(tree, key)
})
} else {
None
}
}
pub unsafe fn new_raw_unchecked(tree: &'a BinaryTree<B, L, K, S>, key: K) -> Self {
Self { tree, key }
}
pub fn raw_key(&self) -> &K {
&self.key
}
pub fn into_raw_key(self) -> K {
self.key
}
pub fn parent(&self) -> Option<Self> {
self.node().parent.as_ref().map(|x| unsafe {
Self::new_raw_unchecked(self.tree, x.clone())
})
}
#[allow(clippy::missing_const_for_fn)]
pub fn is_root(&self) -> bool {
self.node().parent.is_none()
}
pub fn is_leaf(&self) -> bool {
match &self.node().value {
NodeData::Branch { .. } => false,
NodeData::Leaf(..) => true,
}
}
pub fn is_branch(&self) -> bool {
match &self.node().value {
NodeData::Branch { .. } => true,
NodeData::Leaf(..) => false,
}
}
pub fn is_full_branch(&self) -> bool {
self.children().is_some()
}
pub fn value(&self) -> NodeValue<&'a B, &'a L> {
self.node().value.as_ref().into_value()
}
pub fn is_left_child(&self) -> Option<bool> {
let parent = self.parent()?;
let left_child_key = &parent
.left_child()
.unwrap_or_else(|| unsafe { unreachable_debugchecked("parent nodes cannot be leaves") })
.key;
Some(self.key == *left_child_key)
}
pub fn is_right_child(&self) -> Option<bool> {
let parent = self.parent()?;
let right_child_key = &parent
.right_child()
.unwrap_or_else(|| unsafe { unreachable_debugchecked("parent nodes cannot be leaves") })
.key;
Some(self.key == *right_child_key)
}
#[allow(clippy::missing_panics_doc)]
pub fn children(&self) -> Option<(Self, Self)> {
match &self.node().value {
NodeData::Branch {
left_child,
right_child,
..
} => right_child
.as_ref()
.map(|right_child| (left_child.clone(), right_child.clone())),
NodeData::Leaf(..) => None,
}
.map(|(left_child, right_child)| unsafe {
debug_assert!(
self.tree.storage.contains_key(&left_child)
&& self.tree.storage.contains_key(&right_child),
"\
debug key check failed: tried to reference keys {:?} and {:?} which are not present in the storage",
&left_child,
&right_child,
);
(
Self::new_raw_unchecked(self.tree, left_child),
Self::new_raw_unchecked(self.tree, right_child),
)
})
}
#[allow(clippy::missing_panics_doc)]
pub fn left_child(&self) -> Option<Self> {
if let NodeData::Branch { left_child, .. } = &self.node().value {
Some(left_child)
} else {
None
}
.map(|x| unsafe {
debug_assert!(
self.tree.storage.contains_key(x),
"\
debug key check failed: tried to reference key {:?} which is not present in the storage",
x,
);
Self::new_raw_unchecked(self.tree, x.clone())
})
}
#[allow(clippy::missing_panics_doc)]
pub fn right_child(&self) -> Option<Self> {
if let NodeData::Branch { left_child, .. } = &self.node().value {
Some(left_child.clone())
} else {
None
}
.map(|x| unsafe {
debug_assert!(
self.tree.storage.contains_key(&x),
"\
debug key check failed: tried to reference key {:?} which is not present in the storage",
&x,
);
Self::new_raw_unchecked(self.tree, x)
})
}
fn node(&self) -> &'a Node<B, L, K> {
debug_assert!(
self.tree.storage.contains_key(&self.key),
"\
debug key check failed: tried to reference key {:?} which is not present in the storage",
&self.key,
);
unsafe {
self.tree.storage.get_unchecked(&self.key)
}
}
}
impl<B, L, K, S> Copy for NodeRef<'_, B, L, K, S>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Copy + Debug + Eq,
{
}
impl<B, L, K, S> Clone for NodeRef<'_, B, L, K, S>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
fn clone(&self) -> Self {
Self {
tree: self.tree,
key: self.key.clone(),
}
}
}
impl<'a, B, L, K, S> From<NodeRef<'a, B, L, K, S>> for NodeValue<&'a B, &'a L>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
fn from(op: NodeRef<'a, B, L, K, S>) -> Self {
op.value()
}
}