]> git.proxmox.com Git - rustc.git/blame - library/alloc/src/collections/btree/remove.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / library / alloc / src / collections / btree / remove.rs
CommitLineData
29967ef6 1use super::map::MIN_LEN;
fc512014 2use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef};
29967ef6
XL
3
4impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV> {
fc512014
XL
5 /// Removes a key-value pair from the tree, and returns that pair, as well as
6 /// the leaf edge corresponding to that former pair. It's possible this empties
7 /// a root node that is internal, which the caller should pop from the map
8 /// holding the tree. The caller should also decrement the map's length.
29967ef6
XL
9 pub fn remove_kv_tracking<F: FnOnce()>(
10 self,
11 handle_emptied_internal_root: F,
12 ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
fc512014
XL
13 match self.force() {
14 Leaf(node) => node.remove_leaf_kv(handle_emptied_internal_root),
15 Internal(node) => node.remove_internal_kv(handle_emptied_internal_root),
16 }
17 }
18}
29967ef6 19
fc512014
XL
20impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV> {
21 fn remove_leaf_kv<F: FnOnce()>(
22 self,
23 handle_emptied_internal_root: F,
24 ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
25 let (old_kv, mut pos) = self.remove();
26 let len = pos.reborrow().into_node().len();
27 if len < MIN_LEN {
28 let idx = pos.idx();
29 // We have to temporarily forget the child type, because there is no
30 // distinct node type for the immediate parents of a leaf.
31 let new_pos = match pos.into_node().forget_type().choose_parent_kv() {
32 Ok(Left(left_parent_kv)) => {
33 debug_assert!(left_parent_kv.right_child_len() == MIN_LEN - 1);
34 if left_parent_kv.can_merge() {
5869c6ff 35 left_parent_kv.merge_tracking_child_edge(Right(idx))
29967ef6 36 } else {
fc512014
XL
37 debug_assert!(left_parent_kv.left_child_len() > MIN_LEN);
38 left_parent_kv.steal_left(idx)
29967ef6
XL
39 }
40 }
fc512014
XL
41 Ok(Right(right_parent_kv)) => {
42 debug_assert!(right_parent_kv.left_child_len() == MIN_LEN - 1);
43 if right_parent_kv.can_merge() {
5869c6ff 44 right_parent_kv.merge_tracking_child_edge(Left(idx))
fc512014
XL
45 } else {
46 debug_assert!(right_parent_kv.right_child_len() > MIN_LEN);
47 right_parent_kv.steal_right(idx)
29967ef6 48 }
29967ef6 49 }
fc512014
XL
50 Err(pos) => unsafe { Handle::new_edge(pos, idx) },
51 };
52 // SAFETY: `new_pos` is the leaf we started from or a sibling.
53 pos = unsafe { new_pos.cast_to_leaf_unchecked() };
29967ef6 54
fc512014
XL
55 // Only if we merged, the parent (if any) has shrunk, but skipping
56 // the following step otherwise does not pay off in benchmarks.
57 //
58 // SAFETY: We won't destroy or rearrange the leaf where `pos` is at
59 // by handling its parent recursively; at worst we will destroy or
60 // rearrange the parent through the grandparent, thus change the
61 // link to the parent inside the leaf.
62 if let Ok(parent) = unsafe { pos.reborrow_mut() }.into_node().ascend() {
6a06907d
XL
63 if !parent.into_node().forget_type().fix_node_and_affected_ancestors() {
64 handle_emptied_internal_root();
65 }
fc512014 66 }
29967ef6 67 }
29967ef6
XL
68 (old_kv, pos)
69 }
70}
71
fc512014
XL
72impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::KV> {
73 fn remove_internal_kv<F: FnOnce()>(
74 self,
75 handle_emptied_internal_root: F,
76 ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
77 // Remove an adjacent KV from its leaf and then put it back in place of
78 // the element we were asked to remove. Prefer the left adjacent KV,
79 // for the reasons listed in `choose_parent_kv`.
80 let left_leaf_kv = self.left_edge().descend().last_leaf_edge().left_kv();
6a06907d 81 let left_leaf_kv = unsafe { left_leaf_kv.ok().unwrap_unchecked() };
fc512014 82 let (left_kv, left_hole) = left_leaf_kv.remove_leaf_kv(handle_emptied_internal_root);
29967ef6 83
fc512014
XL
84 // The internal node may have been stolen from or merged. Go back right
85 // to find where the original KV ended up.
6a06907d 86 let mut internal = unsafe { left_hole.next_kv().ok().unwrap_unchecked() };
fc512014
XL
87 let old_kv = internal.replace_kv(left_kv.0, left_kv.1);
88 let pos = internal.next_leaf_edge();
89 (old_kv, pos)
90 }
91}