use alloc::vec::Vec;
use crate::{
allocator::Allocator,
raw::{
match_concrete_node_ptr, ConcreteNodePtr, InnerNode, LeafNode, NodePtr, OpaqueNodePtr,
RawIterator,
},
};
pub unsafe fn deallocate_leaves<K, V, const PREFIX_LEN: usize, A: Allocator>(
mut leaf_range: RawIterator<K, V, PREFIX_LEN>,
alloc: &A,
) {
while let Some(leaf_ptr) = unsafe { leaf_range.next() } {
let _ = unsafe { NodePtr::deallocate_node_ptr(leaf_ptr, alloc) };
}
}
pub unsafe fn deallocate_tree_non_leaves<K, V, const PREFIX_LEN: usize, A: Allocator>(
root: OpaqueNodePtr<K, V, PREFIX_LEN>,
alloc: &A,
) {
fn not_leaf<K, V, const PREFIX_LEN: usize>(node: &OpaqueNodePtr<K, V, PREFIX_LEN>) -> bool {
!node.is::<LeafNode<K, V, PREFIX_LEN>>()
}
if root.is::<LeafNode<K, V, PREFIX_LEN>>() {
return;
}
let mut stack = Vec::new();
stack.push(root);
while let Some(next_node_ptr) = stack.pop() {
match_concrete_node_ptr!(match (next_node_ptr.to_node_ptr()) {
InnerNode(inner_ptr) => unsafe {
deallocate_inner_node(&mut stack, inner_ptr, not_leaf, alloc)
},
LeafNode(_leaf) => {
unreachable!("should never encounter a leaf node")
},
})
}
}
pub unsafe fn deallocate_tree<K, V, const PREFIX_LEN: usize, A: Allocator>(
root: OpaqueNodePtr<K, V, PREFIX_LEN>,
alloc: &A,
) -> usize {
fn accept_all<K, V, const PREFIX_LEN: usize>(_: &OpaqueNodePtr<K, V, PREFIX_LEN>) -> bool {
true
}
let mut count = 0;
let mut stack = Vec::new();
stack.push(root);
while let Some(next_node_ptr) = stack.pop() {
match_concrete_node_ptr!(match (next_node_ptr.to_node_ptr()) {
InnerNode(inner_ptr) => unsafe {
deallocate_inner_node(&mut stack, inner_ptr, accept_all, alloc)
},
LeafNode(inner) => {
drop(unsafe { NodePtr::deallocate_node_ptr(inner, alloc) });
count += 1;
},
})
}
count
}
unsafe fn deallocate_inner_node<K, V, N, A: Allocator, const PREFIX_LEN: usize>(
stack: &mut Vec<OpaqueNodePtr<K, V, PREFIX_LEN>>,
inner_ptr: NodePtr<PREFIX_LEN, N>,
filter_children: for<'a> fn(&'a OpaqueNodePtr<K, V, PREFIX_LEN>) -> bool,
alloc: &A,
) where
N: InnerNode<PREFIX_LEN, Key = K, Value = V>,
{
{
let inner_node = unsafe { inner_ptr.as_ref() };
let iter = inner_node.iter();
stack.extend(iter.map(|(_, child)| child).filter(filter_children));
}
drop(unsafe { NodePtr::deallocate_node_ptr(inner_ptr, alloc) });
}