use core::fmt::Debug;
use crate::{
Storage,
DefaultStorage,
NodeValue,
util::{ArrayMap, unreachable_debugchecked},
};
use super::{Quadtree, 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 Quadtree<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 Quadtree<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 Quadtree<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 value(&self) -> NodeValue<&'a B, &'a L> {
self.node().value.as_ref().into_value()
}
pub fn child_index(&self) -> Option<u8> {
let parent = self.parent()?;
for (sibling, index) in parent
.children()
.unwrap_or_else(|| unsafe { unreachable_debugchecked("parent nodes cannot be leaves") })
.iter()
.zip(0_u8..)
{
if sibling.key == self.key {
return Some(index);
}
}
unsafe { unreachable_debugchecked("failed to find node in parent's child list") }
}
#[allow(clippy::missing_panics_doc)]
pub fn children(&self) -> Option<[Self; 4]> {
if let NodeData::Branch { children, .. } = &self.node().value {
Some(children)
} else {
None
}
.map(|children| unsafe {
for c in children {
debug_assert!(
self.tree.storage.contains_key(c),
"\
debug key check failed: tried to reference key {:?} which is not present in the storage",
c,
);
}
children.array_map_by_ref(|child| {
NodeRef::new_raw_unchecked(self.tree, child.clone())
})
})
}
pub fn nth_child(&self, n: u8) -> Option<Self> {
assert!(
n < 4,
"\
quadtrees have either 0 or 4 children, at indicies \
from 0 to 3, but child at index {} was requested",
n,
);
if let NodeData::Branch { children, .. } = &self.node().value {
Some(children)
} else {
None
}
.map(|children| unsafe {
let child = children.get_unchecked(n as usize);
debug_assert!(
self.tree.storage.contains_key(child),
"\
debug key check failed: tried to reference key {:?} which is not present in the storage",
child,
);
Self::new_raw_unchecked(self.tree, child.clone())
})
}
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()
}
}