use core::{fmt::Debug, ptr, convert, hint};
use crate::{
Storage,
DefaultStorage,
NodeValue,
TryRemoveChildrenError,
MakeBranchError,
traversal::algorithms,
util::{ArrayMap, abort_on_panic, unreachable_debugchecked},
};
use super::{Quadtree, Node, NodeData, PackedChildren, NodeRef};
#[derive(Debug)]
pub struct NodeRefMut<'a, B, L, K, S = DefaultStorage<Node<B, L, K>>>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
tree: &'a mut Quadtree<B, L, K, S>,
key: K,
}
impl<'a, B, L, K, S> NodeRefMut<'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 mut 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 mut 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<NodeRef<'_, B, L, K, S>> {
self.node().parent.as_ref().map(|x| unsafe {
NodeRef::new_raw_unchecked(self.tree, x.clone())
})
}
pub fn parent_mut(&mut self) -> Option<NodeRefMut<'_, B, L, K, S>> {
let key = self.node().parent.as_ref().cloned();
key.map(move |x| unsafe {
Self::new_raw_unchecked(self.tree, x)
})
}
#[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<&'_ B, &'_ L> {
self.node().value.as_ref().into_value()
}
pub fn value_mut(&mut self) -> NodeValue<&'_ mut B, &'_ mut L> {
self.node_mut().value.as_mut().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<[NodeRef<'_, B, L, K, S>; 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,
);
}
let [child_0, child_1, child_2, child_3] = children.clone();
[
NodeRef::new_raw_unchecked(self.tree, child_0),
NodeRef::new_raw_unchecked(self.tree, child_1),
NodeRef::new_raw_unchecked(self.tree, child_2),
NodeRef::new_raw_unchecked(self.tree, child_3),
]
})
}
pub fn nth_child(&self, n: u8) -> Option<NodeRef<'_, B, L, K, S>> {
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,
);
NodeRef::new_raw_unchecked(self.tree, child.clone())
})
}
pub fn nth_child_mut(&mut self, n: u8) -> Option<NodeRefMut<'_, B, L, K, S>> {
assert!(
n < 4,
"\
quadtrees have either 0 or 4 children, at indicies \
from 0 to 3, but child at index {} was requested",
n,
);
let children = if let NodeData::Branch { children, .. } = &self.node().value {
Some(children)
} else {
None
}
.cloned();
children.map(move |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())
})
}
pub fn make_branch_with(
&mut self,
children: [L; 4],
leaf_to_branch: impl FnOnce(L) -> B,
) -> Result<(), MakeBranchError<L, PackedChildren<L>>> {
let old_payload_ref = if let NodeData::Leaf(val) = &self.node().value {
val
} else {
return Err(MakeBranchError {
packed_children: children.into(),
});
};
let old_payload = unsafe {
ptr::read(old_payload_ref)
};
let payload = leaf_to_branch(old_payload);
let self_key = self.raw_key().clone();
let children = children.array_map(|value| {
self.tree.storage.add(unsafe {
Node::leaf(value, Some(self_key.clone()))
})
});
unsafe {
ptr::write(
&mut self.node_mut().value,
NodeData::Branch { children, payload },
)
}
Ok(())
}
pub fn try_remove_children_with(
&mut self,
branch_to_leaf: impl FnOnce(B) -> L,
) -> Result<[L; 4], TryRemoveChildrenError> {
let children_keys = {
let children_keys = if let NodeData::Branch { children, .. } = &self.node().value {
Some(children)
} else {
None
}
.ok_or(TryRemoveChildrenError::WasLeafNode)?;
for (c, i) in children_keys.iter().zip(0_u32..) {
let child_ref = unsafe {
self.tree.storage.get_unchecked(c)
};
match &child_ref.value {
NodeData::Branch { .. } => {
return Err(TryRemoveChildrenError::HadBranchChild(i))
}
NodeData::Leaf(..) => {}
};
}
children_keys.clone() };
let children_payloads = children_keys.array_map(|key| {
let node = self.tree.storage.remove(&key);
match node.value.into_value() {
NodeValue::Leaf(val) => val,
NodeValue::Branch(..) => unsafe {
hint::unreachable_unchecked()
},
}
});
let old_payload_ref = if let NodeData::Branch { payload, .. } = &self.node().value {
payload
} else {
unsafe {
hint::unreachable_unchecked()
}
};
let old_payload = unsafe {
ptr::read(old_payload_ref)
};
unsafe {
ptr::write(
&mut self.node_mut().value,
NodeData::Leaf(abort_on_panic(|| branch_to_leaf(old_payload))),
);
}
Ok(children_payloads)
}
pub fn recursively_remove_with(self, branch_to_leaf: impl FnMut(B) -> L) -> NodeValue<B, L> {
algorithms::recursively_remove_with(self.tree, self.key, branch_to_leaf)
}
fn node(&self) -> &'_ 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)
}
}
fn node_mut(&mut self) -> &'_ mut 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_mut(&self.key)
}
}
}
impl<'a, D, K, S> NodeRefMut<'a, D, D, K, S>
where
S: Storage<Element = Node<D, D, K>, Key = K>,
K: Clone + Debug + Eq,
{
pub fn make_branch(
&mut self,
children: [D; 4],
) -> Result<(), MakeBranchError<D, PackedChildren<D>>> {
self.make_branch_with(children, convert::identity)
}
pub fn try_remove_children(&mut self) -> Result<[D; 4], TryRemoveChildrenError> {
self.try_remove_children_with(convert::identity)
}
pub fn recursively_remove(self) -> NodeValue<D> {
algorithms::recursively_remove(self.tree, self.key)
}
}
impl<'a, B, L, K, S> From<&'a NodeRefMut<'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: &'a NodeRefMut<'a, B, L, K, S>) -> Self {
op.value()
}
}
impl<'a, B, L, K, S> From<&'a mut NodeRefMut<'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: &'a mut NodeRefMut<'a, B, L, K, S>) -> Self {
op.value()
}
}
impl<'a, B, L, K, S> From<&'a mut NodeRefMut<'a, B, L, K, S>> for NodeValue<&'a mut B, &'a mut L>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
fn from(op: &'a mut NodeRefMut<'a, B, L, K, S>) -> Self {
op.value_mut()
}
}
impl<'a, B, L, K, S> From<&'a NodeRefMut<'a, B, L, K, S>> for NodeRef<'a, B, L, K, S>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
fn from(op: &'a NodeRefMut<'a, B, L, K, S>) -> Self {
NodeRef {
tree: op.tree as &'a _,
key: op.key.clone(),
}
}
}
impl<'a, B, L, K, S> From<&'a mut NodeRefMut<'a, B, L, K, S>> for NodeRef<'a, B, L, K, S>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
fn from(op: &'a mut NodeRefMut<'a, B, L, K, S>) -> Self {
NodeRef {
tree: op.tree as &'a _,
key: op.key.clone(),
}
}
}
impl<'a, B, L, K, S> From<NodeRefMut<'a, B, L, K, S>> for NodeRef<'a, B, L, K, S>
where
S: Storage<Element = Node<B, L, K>, Key = K>,
K: Clone + Debug + Eq,
{
fn from(op: NodeRefMut<'a, B, L, K, S>) -> Self {
NodeRef {
tree: op.tree as &'a _,
key: op.key,
}
}
}