Skip to main content

alloc/collections/btree/
split.rs

1use core::alloc::AllocatorClone;
2use core::borrow::Borrow;
3use core::{intrinsics, mem};
4
5use super::node::ForceResult::*;
6use super::node::Root;
7use super::search::SearchResult::*;
8
9impl<K, V> Root<K, V> {
10    /// Calculates the length of both trees that result from splitting up
11    /// a given number of distinct key-value pairs.
12    pub(super) fn calc_split_length(
13        total_num: usize,
14        root_a: &Root<K, V>,
15        root_b: &Root<K, V>,
16    ) -> (usize, usize) {
17        let (length_a, length_b);
18        if root_a.height() < root_b.height() {
19            length_a = root_a.reborrow().calc_length();
20            length_b = total_num - length_a;
21            if true {
    {
        match (&length_b, &root_b.reborrow().calc_length()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(length_b, root_b.reborrow().calc_length());
22        } else {
23            length_b = root_b.reborrow().calc_length();
24            length_a = total_num - length_b;
25            if true {
    {
        match (&length_a, &root_a.reborrow().calc_length()) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(length_a, root_a.reborrow().calc_length());
26        }
27        (length_a, length_b)
28    }
29
30    /// Split off a tree with key-value pairs at and after the given key.
31    /// The result is meaningful only if the tree is ordered by key,
32    /// and if the ordering of `Q` corresponds to that of `K`.
33    /// If `self` respects all `BTreeMap` tree invariants, then both
34    /// `self` and the returned tree will respect those invariants.
35    pub(super) fn split_off<Q: ?Sized + Ord, A: AllocatorClone>(
36        &mut self,
37        key: &Q,
38        alloc: A,
39    ) -> Self
40    where
41        K: Borrow<Q>,
42    {
43        let left_root = self;
44        let mut right_root = Root::new_pillar(left_root.height(), alloc.clone());
45        let mut left_node = left_root.borrow_mut();
46        let mut right_node = right_root.borrow_mut();
47
48        // The first search runs before anything has moved, so a panic from the
49        // caller's `Ord`/`Borrow` impl here can unwind safely: `self` is
50        // untouched and the new right tree is still empty.
51        let mut split_edge = match left_node.search_node(key) {
52            // key is going to the right tree
53            Found(kv) => kv.left_edge(),
54            GoDown(edge) => edge,
55        };
56
57        // From the first `move_suffix` on, `left_root` and `right_root` share
58        // key-value pairs through two temporarily invalid tree structures, and
59        // neither is independently droppable until `fix_right_border` /
60        // `fix_left_border` repair them and the caller recomputes both lengths.
61        // A panic from a later `search_node` comparison would unwind out of
62        // that state and double-free the shared values (#158165), so abort
63        // instead of exposing it.
64        let guard = mem::DropGuard::new((), |()| intrinsics::abort());
65
66        loop {
67            split_edge.move_suffix(&mut right_node);
68
69            match (split_edge.force(), right_node.force()) {
70                (Internal(edge), Internal(node)) => {
71                    left_node = edge.descend();
72                    right_node = node.first_edge().descend();
73                }
74                (Leaf(_), Leaf(_)) => break,
75                _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
76            }
77
78            split_edge = match left_node.search_node(key) {
79                Found(kv) => kv.left_edge(),
80                GoDown(edge) => edge,
81            };
82        }
83
84        left_root.fix_right_border(alloc.clone());
85        right_root.fix_left_border(alloc);
86        mem::DropGuard::dismiss(guard);
87        right_root
88    }
89
90    /// Creates a tree consisting of empty nodes.
91    fn new_pillar<A: AllocatorClone>(height: usize, alloc: A) -> Self {
92        let mut root = Root::new(alloc.clone());
93        for _ in 0..height {
94            root.push_internal_level(alloc.clone());
95        }
96        root
97    }
98}