blob: 653218972314f374e0cc87bc3d513b74eacbcfc4 [file] [log] [blame]
use core::ptr;
use super::node::{marker, ForceResult::*, Handle, NodeRef};
use super::unwrap_unchecked;
macro_rules! def_next {
{ unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => {
/// Given a leaf edge handle into an immutable tree, returns a handle to the next
/// leaf edge and references to the key and value between these edges.
/// Unsafe because the caller must ensure that the given leaf edge has a successor.
unsafe fn $name <'a, K: 'a, V: 'a>(
leaf_edge: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
) -> (Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>, &'a K, &'a V) {
let mut cur_handle = match leaf_edge.$next_kv() {
Ok(leaf_kv) => {
let (k, v) = leaf_kv.into_kv();
let next_leaf_edge = leaf_kv.$next_edge();
return (next_leaf_edge, k, v);
}
Err(last_edge) => {
let next_level = last_edge.into_node().ascend().ok();
unwrap_unchecked(next_level)
}
};
loop {
cur_handle = match cur_handle.$next_kv() {
Ok(internal_kv) => {
let (k, v) = internal_kv.into_kv();
let next_internal_edge = internal_kv.$next_edge();
let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge();
return (next_leaf_edge, k, v);
}
Err(last_edge) => {
let next_level = last_edge.into_node().ascend().ok();
unwrap_unchecked(next_level)
}
}
}
}
};
}
macro_rules! def_next_mut {
{ unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => {
/// Given a leaf edge handle into a mutable tree, returns handles to the next
/// leaf edge and to the KV between these edges.
/// Unsafe for two reasons:
/// - the caller must ensure that the given leaf edge has a successor;
/// - both returned handles represent mutable references into the same tree
/// that can easily invalidate each other, even on immutable use.
unsafe fn $name <'a, K: 'a, V: 'a>(
leaf_edge: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
) -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>) {
let mut cur_handle = match leaf_edge.$next_kv() {
Ok(leaf_kv) => {
let next_leaf_edge = ptr::read(&leaf_kv).$next_edge();
return (next_leaf_edge, leaf_kv.forget_node_type());
}
Err(last_edge) => {
let next_level = last_edge.into_node().ascend().ok();
unwrap_unchecked(next_level)
}
};
loop {
cur_handle = match cur_handle.$next_kv() {
Ok(internal_kv) => {
let next_internal_edge = ptr::read(&internal_kv).$next_edge();
let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge();
return (next_leaf_edge, internal_kv.forget_node_type());
}
Err(last_edge) => {
let next_level = last_edge.into_node().ascend().ok();
unwrap_unchecked(next_level)
}
}
}
}
};
}
macro_rules! def_next_dealloc {
{ unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => {
/// Given a leaf edge handle into an owned tree, returns a handle to the next
/// leaf edge and the key and value between these edges, while deallocating
/// any node left behind.
/// Unsafe for two reasons:
/// - the caller must ensure that the given leaf edge has a successor;
/// - the node pointed at by the given handle, and its ancestors, may be deallocated,
/// while the reference to those nodes in the surviving ancestors is left dangling;
/// thus using the returned handle is dangerous.
unsafe fn $name <K, V>(
leaf_edge: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
) -> (Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>, K, V) {
let mut cur_handle = match leaf_edge.$next_kv() {
Ok(leaf_kv) => {
let k = ptr::read(leaf_kv.reborrow().into_kv().0);
let v = ptr::read(leaf_kv.reborrow().into_kv().1);
let next_leaf_edge = leaf_kv.$next_edge();
return (next_leaf_edge, k, v);
}
Err(last_edge) => {
unwrap_unchecked(last_edge.into_node().deallocate_and_ascend())
}
};
loop {
cur_handle = match cur_handle.$next_kv() {
Ok(internal_kv) => {
let k = ptr::read(internal_kv.reborrow().into_kv().0);
let v = ptr::read(internal_kv.reborrow().into_kv().1);
let next_internal_edge = internal_kv.$next_edge();
let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge();
return (next_leaf_edge, k, v);
}
Err(last_edge) => {
unwrap_unchecked(last_edge.into_node().deallocate_and_ascend())
}
}
}
}
};
}
def_next! {unsafe fn next_unchecked: right_kv right_edge first_leaf_edge}
def_next! {unsafe fn next_back_unchecked: left_kv left_edge last_leaf_edge}
def_next_mut! {unsafe fn next_unchecked_mut: right_kv right_edge first_leaf_edge}
def_next_mut! {unsafe fn next_back_unchecked_mut: left_kv left_edge last_leaf_edge}
def_next_dealloc! {unsafe fn next_unchecked_deallocating: right_kv right_edge first_leaf_edge}
def_next_dealloc! {unsafe fn next_back_unchecked_deallocating: left_kv left_edge last_leaf_edge}
impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge> {
/// Moves the leaf edge handle to the next leaf edge and returns references to the
/// key and value in between.
/// Unsafe because the caller must ensure that the leaf edge is not the last one in the tree.
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
let (next_edge, k, v) = next_unchecked(*self);
*self = next_edge;
(k, v)
}
/// Moves the leaf edge handle to the previous leaf edge and returns references to the
/// key and value in between.
/// Unsafe because the caller must ensure that the leaf edge is not the first one in the tree.
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
let (next_edge, k, v) = next_back_unchecked(*self);
*self = next_edge;
(k, v)
}
}
impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge> {
/// Moves the leaf edge handle to the next leaf edge and returns references to the
/// key and value in between.
/// Unsafe for two reasons:
/// - The caller must ensure that the leaf edge is not the last one in the tree.
/// - Using the updated handle may well invalidate the returned references.
pub unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
let (next_edge, kv) = next_unchecked_mut(ptr::read(self));
*self = next_edge;
// Doing the descend (and perhaps another move) invalidates the references
// returned by `into_kv_mut`, so we have to do this last.
kv.into_kv_mut()
}
/// Moves the leaf edge handle to the previous leaf and returns references to the
/// key and value in between.
/// Unsafe for two reasons:
/// - The caller must ensure that the leaf edge is not the first one in the tree.
/// - Using the updated handle may well invalidate the returned references.
pub unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
let (next_edge, kv) = next_back_unchecked_mut(ptr::read(self));
*self = next_edge;
// Doing the descend (and perhaps another move) invalidates the references
// returned by `into_kv_mut`, so we have to do this last.
kv.into_kv_mut()
}
}
impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
/// Moves the leaf edge handle to the next leaf edge and returns the key and value
/// in between, while deallocating any node left behind.
/// Unsafe for three reasons:
/// - The caller must ensure that the leaf edge is not the last one in the tree
/// and is not a handle previously resulting from counterpart `next_back_unchecked`.
/// - If the leaf edge is the last edge of a node, that node and possibly ancestors
/// will be deallocated, while the reference to those nodes in the surviving ancestor
/// is left dangling; thus further use of the leaf edge handle is dangerous.
/// It is, however, safe to call this method again on the updated handle.
/// if the two preconditions above hold.
/// - Using the updated handle may well invalidate the returned references.
pub unsafe fn next_unchecked(&mut self) -> (K, V) {
let (next_edge, k, v) = next_unchecked_deallocating(ptr::read(self));
*self = next_edge;
(k, v)
}
/// Moves the leaf edge handle to the previous leaf edge and returns the key
/// and value in between, while deallocating any node left behind.
/// Unsafe for three reasons:
/// - The caller must ensure that the leaf edge is not the first one in the tree
/// and is not a handle previously resulting from counterpart `next_unchecked`.
/// - If the lead edge is the first edge of a node, that node and possibly ancestors
/// will be deallocated, while the reference to those nodes in the surviving ancestor
/// is left dangling; thus further use of the leaf edge handle is dangerous.
/// It is, however, safe to call this method again on the updated handle.
/// if the two preconditions above hold.
/// - Using the updated handle may well invalidate the returned references.
pub unsafe fn next_back_unchecked(&mut self) -> (K, V) {
let (next_edge, k, v) = next_back_unchecked_deallocating(ptr::read(self));
*self = next_edge;
(k, v)
}
}
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
/// Returns the leftmost leaf edge in or underneath a node - in other words, the edge
/// you need first when navigating forward (or last when navigating backward).
#[inline]
pub fn first_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
let mut node = self;
loop {
match node.force() {
Leaf(leaf) => return leaf.first_edge(),
Internal(internal) => node = internal.first_edge().descend(),
}
}
}
/// Returns the rightmost leaf edge in or underneath a node - in other words, the edge
/// you need last when navigating forward (or first when navigating backward).
#[inline]
pub fn last_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
let mut node = self;
loop {
match node.force() {
Leaf(leaf) => return leaf.last_edge(),
Internal(internal) => node = internal.last_edge().descend(),
}
}
}
}