Skip to main content

imbl/nodes/
btree.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use std::borrow::Borrow;
6use std::collections::VecDeque;
7use std::iter::FromIterator;
8use std::mem;
9use std::num::NonZeroUsize;
10use std::ops::{Bound, RangeBounds};
11
12use archery::{SharedPointer, SharedPointerKind};
13use imbl_sized_chunks::Chunk;
14
15pub(crate) use crate::config::ORD_CHUNK_SIZE as NODE_SIZE;
16
17const MEDIAN: usize = NODE_SIZE / 2;
18const THIRD: usize = NODE_SIZE / 3;
19const NUM_CHILDREN: usize = NODE_SIZE + 1;
20
21/// A node in a `B+Tree`.
22///
23/// The main tree representation uses [`Branch`] and [`Leaf`]; this is only used
24/// in places that want to handle either a branch or a leaf.
25#[derive(Debug)]
26pub(crate) enum Node<K, V, P: SharedPointerKind> {
27    Branch(SharedPointer<Branch<K, V, P>, P>),
28    Leaf(SharedPointer<Leaf<K, V>, P>),
29}
30
31impl<K: Ord + std::fmt::Debug, V: std::fmt::Debug, P: SharedPointerKind> Branch<K, V, P> {
32    #[cfg(any(test, fuzzing))]
33    pub(crate) fn check_sane(&self, is_root: bool) -> usize {
34        assert!(self.keys.len() >= if is_root { 1 } else { MEDIAN - 1 });
35        assert_eq!(self.keys.len() + 1, self.children.len());
36        assert!(self.keys.windows(2).all(|w| w[0] < w[1]));
37        match &self.children {
38            Children::Leaves { leaves } => {
39                for i in 0..self.keys.len() {
40                    let left = &leaves[i];
41                    let right = &leaves[i + 1];
42                    assert!(left.keys.last().unwrap().0 < right.keys.first().unwrap().0);
43                }
44                leaves.iter().map(|child| child.check_sane(false)).sum()
45            }
46            Children::Branches { branches, level } => {
47                for i in 0..self.keys.len() {
48                    let left = &branches[i];
49                    let right = &branches[i + 1];
50                    assert!(left.level() == level.get() - 1);
51                    assert!(right.level() == level.get() - 1);
52                }
53                branches.iter().map(|child| child.check_sane(false)).sum()
54            }
55        }
56    }
57}
58impl<K: Ord + std::fmt::Debug, V: std::fmt::Debug> Leaf<K, V> {
59    #[cfg(any(test, fuzzing))]
60    pub(crate) fn check_sane(&self, is_root: bool) -> usize {
61        assert!(self.keys.windows(2).all(|w| w[0].0 < w[1].0));
62        assert!(self.keys.len() >= if is_root { 0 } else { THIRD });
63        self.keys.len()
64    }
65}
66impl<K: Ord + std::fmt::Debug, V: std::fmt::Debug, P: SharedPointerKind> Node<K, V, P> {
67    /// Check invariants
68    #[cfg(any(test, fuzzing))]
69    pub(crate) fn check_sane(&self, is_root: bool) -> usize {
70        match self {
71            Node::Branch(branch) => branch.check_sane(is_root),
72            Node::Leaf(leaf) => leaf.check_sane(is_root),
73        }
74    }
75}
76
77impl<K, V, P: SharedPointerKind> Node<K, V, P> {
78    pub(crate) fn unit(key: K, value: V) -> Self {
79        Node::Leaf(SharedPointer::new(Leaf {
80            keys: Chunk::unit((key, value)),
81        }))
82    }
83
84    fn level(&self) -> usize {
85        match self {
86            Node::Branch(branch) => branch.level(),
87            Node::Leaf(_) => 0,
88        }
89    }
90
91    pub(crate) fn ptr_eq(&self, other: &Self) -> bool {
92        match (self, other) {
93            (Node::Branch(a), Node::Branch(b)) => SharedPointer::ptr_eq(a, b),
94            (Node::Leaf(a), Node::Leaf(b)) => SharedPointer::ptr_eq(a, b),
95            _ => false,
96        }
97    }
98}
99
100/// A branch node in a `B+Tree`.
101/// Invariants:
102/// * keys are ordered and unique
103/// * keys.len() + 1 == children.len()
104/// * all children have level = level - 1 (or level is 1 and all children are leaves)
105/// * all keys in the subtree at children[i] are between keys[i - 1] (if i > 0) and keys[i] (if i < keys.len()).
106/// * root branch must have at least 1 key, whereas non-root branches must have at least MEDIAN - 1 keys
107#[derive(Debug)]
108pub(crate) struct Branch<K, V, P: SharedPointerKind> {
109    keys: Chunk<K, NODE_SIZE>,
110    children: Children<K, V, P>,
111}
112
113#[derive(Debug)]
114pub(crate) enum Children<K, V, P: SharedPointerKind> {
115    /// implicitly level 1
116    Leaves {
117        leaves: Chunk<SharedPointer<Leaf<K, V>, P>, NUM_CHILDREN>,
118    },
119    /// level >= 2
120    Branches {
121        branches: Chunk<SharedPointer<Branch<K, V, P>, P>, NUM_CHILDREN>,
122        /// The level of the tree node that contains these children.
123        ///
124        /// Leaves have level zero, so branches have level at least one. Since this is the
125        /// level of something containing branches, it is at least two.
126        level: NonZeroUsize,
127    },
128}
129
130impl<K, V, P: SharedPointerKind> Children<K, V, P> {
131    fn len(&self) -> usize {
132        match self {
133            Children::Leaves { leaves } => leaves.len(),
134            Children::Branches { branches, .. } => branches.len(),
135        }
136    }
137    fn drain_from_front(&mut self, other: &mut Self, count: usize) {
138        match (self, other) {
139            (
140                Children::Leaves { leaves },
141                Children::Leaves {
142                    leaves: other_leaves,
143                },
144            ) => leaves.drain_from_front(other_leaves, count),
145            (
146                Children::Branches { branches, .. },
147                Children::Branches {
148                    branches: other_branches,
149                    ..
150                },
151            ) => branches.drain_from_front(other_branches, count),
152            _ => panic!("mismatched drain_from_front"),
153        }
154    }
155    fn drain_from_back(&mut self, other: &mut Self, count: usize) {
156        match (self, other) {
157            (
158                Children::Leaves { leaves },
159                Children::Leaves {
160                    leaves: other_leaves,
161                },
162            ) => leaves.drain_from_back(other_leaves, count),
163            (
164                Children::Branches { branches, .. },
165                Children::Branches {
166                    branches: other_branches,
167                    ..
168                },
169            ) => branches.drain_from_back(other_branches, count),
170            _ => panic!("mismatched drain_from_back"),
171        }
172    }
173    fn extend(&mut self, other: &Self) {
174        match (self, other) {
175            (
176                Children::Leaves { leaves },
177                Children::Leaves {
178                    leaves: other_leaves,
179                },
180            ) => leaves.extend(other_leaves.iter().cloned()),
181            (
182                Children::Branches { branches, .. },
183                Children::Branches {
184                    branches: other_branches,
185                    ..
186                },
187            ) => branches.extend(other_branches.iter().cloned()),
188            _ => panic!("mismatched extend"),
189        }
190    }
191    fn insert_front(&mut self, other: &Self) {
192        match (self, other) {
193            (
194                Children::Leaves { leaves },
195                Children::Leaves {
196                    leaves: other_leaves,
197                },
198            ) => leaves.insert_from(0, other_leaves.iter().cloned()),
199            (
200                Children::Branches { branches, .. },
201                Children::Branches {
202                    branches: other_branches,
203                    ..
204                },
205            ) => branches.insert_from(0, other_branches.iter().cloned()),
206            _ => panic!("mismatched insert_front"),
207        }
208    }
209    fn insert(&mut self, index: usize, node: Node<K, V, P>) {
210        match (self, node) {
211            (Children::Leaves { leaves }, Node::Leaf(node)) => leaves.insert(index, node),
212            (Children::Branches { branches, .. }, Node::Branch(node)) => {
213                branches.insert(index, node)
214            }
215            _ => panic!("mismatched insert"),
216        }
217    }
218    fn split_off(&mut self, at: usize) -> Self {
219        match self {
220            Children::Leaves { leaves } => Children::Leaves {
221                leaves: leaves.split_off(at),
222            },
223            Children::Branches { branches, level } => Children::Branches {
224                branches: branches.split_off(at),
225                level: *level,
226            },
227        }
228    }
229}
230
231impl<K, V, P: SharedPointerKind> Branch<K, V, P> {
232    pub(crate) fn pop_single_child(&mut self) -> Option<Node<K, V, P>> {
233        if self.children.len() == 1 {
234            debug_assert_eq!(self.keys.len(), 0);
235            Some(match &mut self.children {
236                Children::Leaves { leaves } => Node::Leaf(leaves.pop_back()),
237                Children::Branches { branches, .. } => Node::Branch(branches.pop_back()),
238            })
239        } else {
240            None
241        }
242    }
243
244    fn level(&self) -> usize {
245        match &self.children {
246            Children::Leaves { .. } => 1,
247            Children::Branches { level, .. } => level.get(),
248        }
249    }
250}
251
252/// A leaf node in a `B+Tree`.
253///
254/// Invariants:
255/// * keys are ordered and unique
256/// * leaf is the lowest level in the tree (level 0)
257/// * non-root leaves must have at least THIRD keys
258#[derive(Debug)]
259pub(crate) struct Leaf<K, V> {
260    keys: Chunk<(K, V), NODE_SIZE>,
261}
262
263impl<K: Ord + Clone, V: Clone, P: SharedPointerKind> Node<K, V, P> {
264    /// Removes a key from the node or its children.
265    /// Returns `true` if the node is underflowed and should be rebalanced.
266    pub(crate) fn remove<BK>(&mut self, key: &BK, removed: &mut Option<(K, V)>) -> bool
267    where
268        BK: Ord + ?Sized,
269        K: Borrow<BK>,
270    {
271        match self {
272            Node::Branch(branch) => SharedPointer::make_mut(branch).remove(key, removed),
273            Node::Leaf(leaf) => SharedPointer::make_mut(leaf).remove(key, removed),
274        }
275    }
276}
277
278impl<K: Ord + Clone, V: Clone, P: SharedPointerKind> Branch<K, V, P> {
279    pub(crate) fn remove<BK>(&mut self, key: &BK, removed: &mut Option<(K, V)>) -> bool
280    where
281        BK: Ord + ?Sized,
282        K: Borrow<BK>,
283    {
284        let i = slice_ext::binary_search_by(&self.keys, |k| k.borrow().cmp(key))
285            .map(|x| x + 1)
286            .unwrap_or_else(|x| x);
287        let rebalance = match &mut self.children {
288            Children::Leaves { leaves } => {
289                SharedPointer::make_mut(&mut leaves[i]).remove(key, removed)
290            }
291            Children::Branches { branches, .. } => {
292                SharedPointer::make_mut(&mut branches[i]).remove(key, removed)
293            }
294        };
295        if rebalance {
296            self.branch_rebalance_children(i);
297        }
298        // Underflow if the branch is < 1/2 full. Since the branches are relatively
299        // rarely rebalanced (given relaxed leaf underflow), we can afford to be
300        // a bit more conservative here.
301        self.keys.len() < MEDIAN
302    }
303}
304
305impl<K: Ord + Clone, V: Clone> Leaf<K, V> {
306    pub(crate) fn remove<BK>(&mut self, key: &BK, removed: &mut Option<(K, V)>) -> bool
307    where
308        BK: Ord + ?Sized,
309        K: Borrow<BK>,
310    {
311        if let Ok(i) = slice_ext::binary_search_by(&self.keys, |(k, _)| k.borrow().cmp(key)) {
312            *removed = Some(self.keys.remove(i));
313        }
314        // Underflow if the leaf is < 1/3 full. This relaxed underflow (vs. 1/2 full) is
315        // useful to prevent degenerate cases where a random insert/remove workload will
316        // constantly merge/split a leaf.
317        self.keys.len() < THIRD
318    }
319}
320
321impl<K: Ord + Clone, V: Clone, P: SharedPointerKind> Branch<K, V, P> {
322    #[cold]
323    pub(crate) fn branch_rebalance_children(&mut self, underflow_idx: usize) {
324        let left_idx = underflow_idx.saturating_sub(1);
325        match &mut self.children {
326            Children::Leaves { leaves } => {
327                let (left, mid, right) = match &leaves[left_idx..] {
328                    [left, mid, right, ..] => (&**left, &**mid, Some(&**right)),
329                    [left, mid, ..] => (&**left, &**mid, None),
330                    _ => return,
331                };
332                // Prefer merging two sibling children if we can fit them into a single node.
333                // But also try to rebalance if the smallest child is small (< 1/3), to amortize the cost of rebalancing.
334                // Since we prefer merging, for rebalancing to apply the the largest child will be least 2/3 full,
335                // which results in two at least half full nodes after rebalancing.
336                match (left, mid, right) {
337                    (left, mid, _) if left.keys.len() + mid.keys.len() <= NODE_SIZE => {
338                        Self::merge_leaves(leaves, &mut self.keys, left_idx, false);
339                    }
340                    (_, mid, Some(right)) if mid.keys.len() + right.keys.len() <= NODE_SIZE => {
341                        Self::merge_leaves(leaves, &mut self.keys, left_idx + 1, true);
342                    }
343                    (left, mid, _) if mid.keys.len().min(left.keys.len()) < THIRD => {
344                        Self::rebalance_leaves(leaves, &mut self.keys, left_idx);
345                    }
346                    (_, mid, Some(right)) if mid.keys.len().min(right.keys.len()) < THIRD => {
347                        Self::rebalance_leaves(leaves, &mut self.keys, left_idx + 1);
348                    }
349                    _ => (),
350                }
351            }
352            Children::Branches { branches, .. } => {
353                let (left, mid, right) = match &branches[left_idx..] {
354                    [left, mid, right, ..] => (&**left, &**mid, Some(&**right)),
355                    [left, mid, ..] => (&**left, &**mid, None),
356                    _ => return,
357                };
358                match (left, mid, right) {
359                    (left, mid, _) if left.keys.len() + mid.keys.len() < NODE_SIZE => {
360                        Self::merge_branches(branches, &mut self.keys, left_idx, false);
361                    }
362                    (_, mid, Some(right)) if mid.keys.len() + right.keys.len() < NODE_SIZE => {
363                        Self::merge_branches(branches, &mut self.keys, left_idx + 1, true);
364                    }
365                    (left, mid, _) if mid.keys.len().min(left.keys.len()) < THIRD => {
366                        Self::rebalance_branches(branches, &mut self.keys, left_idx);
367                    }
368                    (_, mid, Some(right)) if mid.keys.len().min(right.keys.len()) < THIRD => {
369                        Self::rebalance_branches(branches, &mut self.keys, left_idx + 1);
370                    }
371                    _ => (),
372                }
373            }
374        }
375    }
376
377    /// Merges two children leaves of this branch.
378    ///
379    /// Assumes that the two children can fit in a single leaf, panicking if not.
380    fn merge_leaves(
381        children: &mut Chunk<SharedPointer<Leaf<K, V>, P>, NUM_CHILDREN>,
382        keys: &mut Chunk<K, NODE_SIZE>,
383        left_idx: usize,
384        keep_left: bool,
385    ) {
386        let [left, right, ..] = &mut children[left_idx..] else {
387            unreachable!()
388        };
389        if keep_left {
390            let left = SharedPointer::make_mut(left);
391            let (left, right) = (left, &**right);
392            left.keys.extend(right.keys.iter().cloned());
393        } else {
394            let right = SharedPointer::make_mut(right);
395            let (left, right) = (&**left, right);
396            right.keys.insert_from(0, left.keys.iter().cloned());
397        }
398        keys.remove(left_idx);
399        children.remove(left_idx + (keep_left as usize));
400        debug_assert_eq!(keys.len() + 1, children.len());
401    }
402
403    /// Rebalances two adjacent leaves so that they have the same
404    /// number of keys (or differ by at most 1).
405    fn rebalance_leaves(
406        children: &mut Chunk<SharedPointer<Leaf<K, V>, P>, NUM_CHILDREN>,
407        keys: &mut Chunk<K, NODE_SIZE>,
408        left_idx: usize,
409    ) {
410        let [left, right, ..] = &mut children[left_idx..] else {
411            unreachable!()
412        };
413        let (left, right) = (
414            SharedPointer::make_mut(left),
415            SharedPointer::make_mut(right),
416        );
417        let num_to_move = left.keys.len().abs_diff(right.keys.len()) / 2;
418        if num_to_move == 0 {
419            return;
420        }
421        if left.keys.len() > right.keys.len() {
422            right.keys.drain_from_back(&mut left.keys, num_to_move);
423        } else {
424            left.keys.drain_from_front(&mut right.keys, num_to_move);
425        }
426        keys[left_idx] = right.keys.first().unwrap().0.clone();
427        debug_assert_ne!(left.keys.len(), 0);
428        debug_assert_ne!(right.keys.len(), 0);
429    }
430
431    /// Rebalances two adjacent child branches so that they have the same number of keys
432    /// (or differ by at most 1). The separator key is rotated between the two branches.
433    /// to keep the invariants of the parent branch.
434    fn rebalance_branches(
435        children: &mut Chunk<SharedPointer<Branch<K, V, P>, P>, NUM_CHILDREN>,
436        keys: &mut Chunk<K, NODE_SIZE>,
437        left_idx: usize,
438    ) {
439        let [left, right, ..] = &mut children[left_idx..] else {
440            unreachable!()
441        };
442        let (left, right) = (
443            SharedPointer::make_mut(left),
444            SharedPointer::make_mut(right),
445        );
446        let num_to_move = left.keys.len().abs_diff(right.keys.len()) / 2;
447        if num_to_move == 0 {
448            return;
449        }
450        let separator = &mut keys[left_idx];
451        if left.keys.len() > right.keys.len() {
452            right.keys.push_front(separator.clone());
453            right.keys.drain_from_back(&mut left.keys, num_to_move - 1);
454            *separator = left.keys.pop_back();
455            right
456                .children
457                .drain_from_back(&mut left.children, num_to_move);
458        } else {
459            left.keys.push_back(separator.clone());
460            left.keys.drain_from_front(&mut right.keys, num_to_move - 1);
461            *separator = right.keys.pop_front();
462            left.children
463                .drain_from_front(&mut right.children, num_to_move);
464        }
465        debug_assert_ne!(left.keys.len(), 0);
466        debug_assert_eq!(left.children.len(), left.keys.len() + 1);
467        debug_assert_ne!(right.keys.len(), 0);
468        debug_assert_eq!(right.children.len(), right.keys.len() + 1);
469    }
470
471    /// Merges two children of this branch.
472    ///
473    /// Assumes that the two children can fit in a single branch, panicking if not.
474    fn merge_branches(
475        children: &mut Chunk<SharedPointer<Branch<K, V, P>, P>, NUM_CHILDREN>,
476        keys: &mut Chunk<K, NODE_SIZE>,
477        left_idx: usize,
478        keep_left: bool,
479    ) {
480        let [left, right, ..] = &mut children[left_idx..] else {
481            unreachable!()
482        };
483        let separator = keys.remove(left_idx);
484        if keep_left {
485            let left = SharedPointer::make_mut(left);
486            let (left, right) = (left, &**right);
487            left.keys.push_back(separator);
488            left.keys.extend(right.keys.iter().cloned());
489            left.children.extend(&right.children);
490        } else {
491            let right = SharedPointer::make_mut(right);
492            let (left, right) = (&**left, right);
493            right.keys.push_front(separator);
494            right.keys.insert_from(0, left.keys.iter().cloned());
495            right.children.insert_front(&left.children);
496        }
497        children.remove(left_idx + (keep_left as usize));
498        debug_assert_eq!(keys.len() + 1, children.len());
499    }
500}
501
502impl<K: Ord + Clone, V: Clone, P: SharedPointerKind> Branch<K, V, P> {
503    pub(crate) fn insert(&mut self, key: K, value: V) -> InsertAction<K, V, P> {
504        let i = slice_ext::binary_search_by(&self.keys, |k| k.cmp(&key))
505            .map(|x| x + 1)
506            .unwrap_or_else(|x| x);
507        let insert_action = match &mut self.children {
508            Children::Leaves { leaves } => {
509                SharedPointer::make_mut(&mut leaves[i]).insert(key, value)
510            }
511            Children::Branches { branches, .. } => {
512                SharedPointer::make_mut(&mut branches[i]).insert(key, value)
513            }
514        };
515        match insert_action {
516            InsertAction::Split(new_key, new_node) if self.keys.len() >= NODE_SIZE => {
517                self.split_branch_insert(i, new_key, new_node)
518            }
519            InsertAction::Split(separator, new_node) => {
520                self.keys.insert(i, separator);
521                self.children.insert(i + 1, new_node);
522                InsertAction::Inserted
523            }
524            action => action,
525        }
526    }
527}
528impl<K: Ord + Clone, V: Clone> Leaf<K, V> {
529    pub(crate) fn insert<P: SharedPointerKind>(
530        &mut self,
531        key: K,
532        value: V,
533    ) -> InsertAction<K, V, P> {
534        match slice_ext::binary_search_by(&self.keys, |(k, _)| k.cmp(&key)) {
535            Ok(i) => {
536                let (k, v) = mem::replace(&mut self.keys[i], (key, value));
537                InsertAction::Replaced(k, v)
538            }
539            Err(i) if self.keys.len() >= NODE_SIZE => self.split_leaf_insert(i, key, value),
540            Err(i) => {
541                self.keys.insert(i, (key, value));
542                InsertAction::Inserted
543            }
544        }
545    }
546}
547impl<K: Ord + Clone, V: Clone, P: SharedPointerKind> Node<K, V, P> {
548    pub(crate) fn insert(&mut self, key: K, value: V) -> InsertAction<K, V, P> {
549        match self {
550            Node::Branch(branch) => SharedPointer::make_mut(branch).insert(key, value),
551            Node::Leaf(leaf) => SharedPointer::make_mut(leaf).insert(key, value),
552        }
553    }
554}
555impl<K: Ord + Clone, V: Clone, P: SharedPointerKind> Branch<K, V, P> {
556    #[cold]
557    fn split_branch_insert(
558        &mut self,
559        i: usize,
560        new_key: K,
561        new_node: Node<K, V, P>,
562    ) -> InsertAction<K, V, P> {
563        let split_idx = MEDIAN + (i > MEDIAN) as usize;
564        let mut right_keys = self.keys.split_off(split_idx);
565        let split_idx = MEDIAN + (i >= MEDIAN) as usize;
566        let mut right_children = self.children.split_off(split_idx);
567        let separator = if i == MEDIAN {
568            right_children.insert(0, new_node.clone());
569            new_key
570        } else {
571            if i < MEDIAN {
572                self.keys.insert(i, new_key);
573                self.children.insert(i + 1, new_node);
574            } else {
575                right_keys.insert(i - (MEDIAN + 1), new_key);
576                right_children.insert(i - (MEDIAN + 1) + 1, new_node);
577            }
578            self.keys.pop_back()
579        };
580        debug_assert_eq!(self.keys.len(), right_keys.len());
581        debug_assert_eq!(self.keys.len() + 1, self.children.len());
582        debug_assert_eq!(right_keys.len() + 1, right_children.len());
583        InsertAction::Split(
584            separator,
585            Node::Branch(SharedPointer::new(Branch {
586                keys: right_keys,
587                children: right_children,
588            })),
589        )
590    }
591}
592
593impl<K: Ord + Clone, V: Clone> Leaf<K, V> {
594    #[inline]
595    fn split_leaf_insert<P: SharedPointerKind>(
596        &mut self,
597        i: usize,
598        key: K,
599        value: V,
600    ) -> InsertAction<K, V, P> {
601        let mut right_keys = self.keys.split_off(MEDIAN);
602        if i < MEDIAN {
603            self.keys.insert(i, (key, value));
604        } else {
605            right_keys.insert(i - MEDIAN, (key, value));
606        }
607        InsertAction::Split(
608            right_keys.first().unwrap().0.clone(),
609            Node::Leaf(SharedPointer::new(Leaf { keys: right_keys })),
610        )
611    }
612}
613
614impl<K: Ord + Clone, V: Clone, P: SharedPointerKind> Branch<K, V, P> {
615    pub(crate) fn lookup_mut<BK>(&mut self, key: &BK) -> Option<(&K, &mut V)>
616    where
617        BK: Ord + ?Sized,
618        K: Borrow<BK>,
619    {
620        let i = slice_ext::binary_search_by(&self.keys, |k| k.borrow().cmp(key))
621            .map(|x| x + 1)
622            .unwrap_or_else(|x| x);
623        match &mut self.children {
624            Children::Leaves { leaves } => SharedPointer::make_mut(&mut leaves[i]).lookup_mut(key),
625            Children::Branches { branches, .. } => {
626                SharedPointer::make_mut(&mut branches[i]).lookup_mut(key)
627            }
628        }
629    }
630}
631
632impl<K: Ord + Clone, V: Clone> Leaf<K, V> {
633    pub(crate) fn lookup_mut<BK>(&mut self, key: &BK) -> Option<(&K, &mut V)>
634    where
635        BK: Ord + ?Sized,
636        K: Borrow<BK>,
637    {
638        let keys = &mut self.keys;
639        let i = slice_ext::binary_search_by(keys, |(k, _)| k.borrow().cmp(key)).ok()?;
640        keys.get_mut(i).map(|(k, v)| (&*k, v))
641    }
642}
643
644impl<K: Ord + Clone, V: Clone, P: SharedPointerKind> Node<K, V, P> {
645    pub(crate) fn lookup_mut<BK>(&mut self, key: &BK) -> Option<(&K, &mut V)>
646    where
647        BK: Ord + ?Sized,
648        K: Borrow<BK>,
649    {
650        match self {
651            Node::Branch(branch) => SharedPointer::make_mut(branch).lookup_mut(key),
652            Node::Leaf(leaf) => SharedPointer::make_mut(leaf).lookup_mut(key),
653        }
654    }
655
656    pub(crate) fn new_from_split(left: Self, separator: K, right: Self) -> Self {
657        Node::Branch(SharedPointer::new(Branch {
658            keys: Chunk::unit(separator),
659            children: match (left, right) {
660                (Node::Branch(left), Node::Branch(right)) => Children::Branches {
661                    level: NonZeroUsize::new(left.level() + 1).unwrap(),
662                    branches: Chunk::from_iter([left, right]),
663                },
664                (Node::Leaf(left), Node::Leaf(right)) => Children::Leaves {
665                    leaves: Chunk::from_iter([left, right]),
666                },
667                _ => panic!("mismatched split"),
668            },
669        }))
670    }
671}
672
673impl<K: Ord, V, P: SharedPointerKind> Branch<K, V, P> {
674    fn min(&self) -> Option<&(K, V)> {
675        let mut node = self;
676        loop {
677            match &node.children {
678                Children::Leaves { leaves } => return leaves.first()?.min(),
679                Children::Branches { branches, .. } => node = branches.first()?,
680            }
681        }
682    }
683    fn max(&self) -> Option<&(K, V)> {
684        let mut node = self;
685        loop {
686            match &node.children {
687                Children::Leaves { leaves } => return leaves.last()?.max(),
688                Children::Branches { branches, .. } => node = branches.last()?,
689            }
690        }
691    }
692    pub(crate) fn lookup<BK>(&self, key: &BK) -> Option<&(K, V)>
693    where
694        BK: Ord + ?Sized,
695        K: Borrow<BK>,
696    {
697        let mut node = self;
698        loop {
699            let i = slice_ext::binary_search_by(&node.keys, |k| k.borrow().cmp(key))
700                .map(|x| x + 1)
701                .unwrap_or_else(|x| x);
702            match &node.children {
703                Children::Leaves { leaves } => return leaves[i].lookup(key),
704                Children::Branches { branches, .. } => node = &branches[i],
705            }
706        }
707    }
708}
709
710impl<K: Ord, V> Leaf<K, V> {
711    fn min(&self) -> Option<&(K, V)> {
712        self.keys.first()
713    }
714    fn max(&self) -> Option<&(K, V)> {
715        self.keys.last()
716    }
717    fn lookup<BK>(&self, key: &BK) -> Option<&(K, V)>
718    where
719        BK: Ord + ?Sized,
720        K: Borrow<BK>,
721    {
722        let keys = &self.keys;
723        let i = slice_ext::binary_search_by(keys, |(k, _)| k.borrow().cmp(key)).ok()?;
724        keys.get(i)
725    }
726}
727
728impl<K: Ord, V, P: SharedPointerKind> Node<K, V, P> {
729    pub(crate) fn min(&self) -> Option<&(K, V)> {
730        match self {
731            Node::Branch(branch) => branch.min(),
732            Node::Leaf(leaf) => leaf.min(),
733        }
734    }
735
736    pub(crate) fn max(&self) -> Option<&(K, V)> {
737        match self {
738            Node::Branch(branch) => branch.max(),
739            Node::Leaf(leaf) => leaf.max(),
740        }
741    }
742
743    pub(crate) fn lookup<BK>(&self, key: &BK) -> Option<&(K, V)>
744    where
745        BK: Ord + ?Sized,
746        K: Borrow<BK>,
747    {
748        match self {
749            Node::Branch(branch) => branch.lookup(key),
750            Node::Leaf(leaf) => leaf.lookup(key),
751        }
752    }
753}
754
755impl<K: Clone, V: Clone> Clone for Leaf<K, V> {
756    fn clone(&self) -> Self {
757        Self {
758            keys: self.keys.clone(),
759        }
760    }
761}
762
763impl<K: Clone, V: Clone, P: SharedPointerKind> Clone for Branch<K, V, P> {
764    fn clone(&self) -> Self {
765        Self {
766            keys: self.keys.clone(),
767            children: self.children.clone(),
768        }
769    }
770}
771
772impl<K: Clone, V: Clone, P: SharedPointerKind> Clone for Children<K, V, P> {
773    fn clone(&self) -> Self {
774        match self {
775            Children::Leaves { leaves } => Children::Leaves {
776                leaves: leaves.clone(),
777            },
778            Children::Branches { branches, level } => Children::Branches {
779                branches: branches.clone(),
780                level: *level,
781            },
782        }
783    }
784}
785
786impl<K, V, P: SharedPointerKind> Clone for Node<K, V, P> {
787    fn clone(&self) -> Self {
788        match self {
789            Node::Branch(branch) => Node::Branch(branch.clone()),
790            Node::Leaf(leaf) => Node::Leaf(leaf.clone()),
791        }
792    }
793}
794
795pub(crate) enum InsertAction<K, V, P: SharedPointerKind> {
796    Inserted,
797    Replaced(K, V),
798    Split(K, Node<K, V, P>),
799}
800
801impl<K, V, P: SharedPointerKind> Default for Node<K, V, P> {
802    fn default() -> Self {
803        Node::Leaf(SharedPointer::new(Leaf { keys: Chunk::new() }))
804    }
805}
806
807#[derive(Debug)]
808pub(crate) struct ConsumingIter<K, V, P: SharedPointerKind> {
809    /// The leaves of the tree, in order, note that this will remain the shared ptr
810    /// as it will allows us to have a smaller VecDeque allocation and avoid eagerly
811    /// cloning the leaves, which defeats the purpose of this iterator.
812    /// Leaves present in the VecDeque are guaranteed to be non-empty.
813    leaves: VecDeque<SharedPointer<Leaf<K, V>, P>>,
814    remaining: usize,
815}
816
817impl<K, V, P: SharedPointerKind> ConsumingIter<K, V, P> {
818    pub(crate) fn new(node: Option<Node<K, V, P>>, size: usize) -> Self {
819        fn push<K, V, P: SharedPointerKind>(
820            out: &mut VecDeque<SharedPointer<Leaf<K, V>, P>>,
821            node: SharedPointer<Branch<K, V, P>, P>,
822        ) {
823            match &node.children {
824                Children::Leaves { leaves } => {
825                    out.extend(leaves.iter().filter(|leaf| !leaf.keys.is_empty()).cloned())
826                }
827                Children::Branches { branches, .. } => {
828                    for child in branches.iter() {
829                        push(out, child.clone());
830                    }
831                }
832            }
833        }
834        // preallocate the VecDeque assuming each leaf is half full
835        let mut leaves = VecDeque::with_capacity(size.div_ceil(NODE_SIZE / 2));
836        match node {
837            Some(Node::Branch(b)) => push(&mut leaves, b),
838            Some(Node::Leaf(l)) => {
839                if !l.keys.is_empty() {
840                    leaves.push_back(l)
841                }
842            }
843            None => (),
844        }
845        Self {
846            leaves,
847            remaining: size,
848        }
849    }
850}
851
852impl<K: Clone, V: Clone, P: SharedPointerKind> Iterator for ConsumingIter<K, V, P> {
853    type Item = (K, V);
854
855    fn next(&mut self) -> Option<Self::Item> {
856        let node = self.leaves.front_mut()?;
857        let leaf = SharedPointer::make_mut(node);
858        self.remaining -= 1;
859        let item = leaf.keys.pop_front();
860        if leaf.keys.is_empty() {
861            self.leaves.pop_front();
862        }
863        Some(item)
864    }
865
866    fn size_hint(&self) -> (usize, Option<usize>) {
867        (self.remaining, Some(self.remaining))
868    }
869}
870
871impl<K: Clone, V: Clone, P: SharedPointerKind> DoubleEndedIterator for ConsumingIter<K, V, P> {
872    fn next_back(&mut self) -> Option<Self::Item> {
873        let node = self.leaves.back_mut()?;
874        let leaf = SharedPointer::make_mut(node);
875        self.remaining -= 1;
876        let item = leaf.keys.pop_back();
877        if leaf.keys.is_empty() {
878            self.leaves.pop_back();
879        }
880        Some(item)
881    }
882}
883
884#[derive(Debug)]
885pub(crate) struct Iter<'a, K, V, P: SharedPointerKind> {
886    /// The forward and backward cursors
887    /// The cursors are lazily initialized if their corresponding bound is unbounded
888    fwd: Cursor<'a, K, V, P>,
889    bwd: Cursor<'a, K, V, P>,
890    fwd_yielded: bool,
891    bwd_yielded: bool,
892    exhausted: bool,
893    exact: bool,
894    remaining: usize,
895    root: Option<&'a Node<K, V, P>>,
896}
897
898impl<'a, K, V, P: SharedPointerKind> Iter<'a, K, V, P> {
899    pub(crate) fn new<R, BK>(root: Option<&'a Node<K, V, P>>, len: usize, range: R) -> Self
900    where
901        R: RangeBounds<BK>,
902        K: Borrow<BK>,
903        BK: Ord + ?Sized,
904    {
905        let mut fwd = Cursor::empty();
906        let mut bwd = Cursor::empty();
907        let mut exhausted = match range.start_bound() {
908            Bound::Included(key) | Bound::Excluded(key) => {
909                fwd.init(root);
910                if fwd.seek_to_key(key, false) && matches!(range.start_bound(), Bound::Excluded(_))
911                {
912                    fwd.next().is_none()
913                } else {
914                    fwd.is_empty()
915                }
916            }
917            Bound::Unbounded => false,
918        };
919
920        exhausted = match (exhausted, range.end_bound()) {
921            (false, Bound::Included(key) | Bound::Excluded(key)) => {
922                bwd.init(root);
923                if bwd.seek_to_key(key, true) && matches!(range.end_bound(), Bound::Excluded(_)) {
924                    bwd.prev().is_none()
925                } else {
926                    bwd.is_empty()
927                }
928            }
929            (exhausted, _) => exhausted,
930        };
931
932        // Check if forward is > backward cursor to determine if we are exhausted
933        // Due to the usage of zip this is correct even if the cursors are already or not initialized yet
934        fn cursors_exhausted<K, V, P: SharedPointerKind>(
935            fwd: &Cursor<'_, K, V, P>,
936            bwd: &Cursor<'_, K, V, P>,
937        ) -> bool {
938            for (&(fi, f), &(bi, b)) in fwd.stack.iter().zip(bwd.stack.iter()) {
939                if !std::ptr::eq(f, b) {
940                    return false;
941                }
942                if fi > bi {
943                    return true;
944                }
945            }
946            if let (Some((fi, f)), Some((bi, b))) = (fwd.leaf, bwd.leaf) {
947                if !std::ptr::eq(f, b) {
948                    return false;
949                }
950                if fi > bi {
951                    return true;
952                }
953            }
954            false
955        }
956        exhausted = exhausted || cursors_exhausted(&fwd, &bwd);
957
958        let exact = matches!(range.start_bound(), Bound::Unbounded)
959            && matches!(range.end_bound(), Bound::Unbounded);
960
961        Self {
962            fwd,
963            bwd,
964            remaining: len,
965            exact,
966            exhausted,
967            fwd_yielded: false,
968            bwd_yielded: false,
969            root,
970        }
971    }
972
973    /// Updates the exhausted state of the iterator.
974    /// Returns true if the iterator is immaterially exhausted, which implies ignoring the
975    /// current next candidate, if any.
976    #[inline]
977    fn update_exhausted(&mut self, has_next: bool, other_side_yielded: bool) -> bool {
978        debug_assert!(!self.exhausted);
979        if !has_next {
980            self.exhausted = true;
981            return true;
982        }
983        // Check if the cursors are exhausted by checking their leaves
984        // This is valid even if the cursors are empty due to not being initialized yet.
985        // If they were empty because exhaustion we would not be in this function.
986        if let (Some((fi, f)), Some((bi, b))) = (self.fwd.leaf, self.bwd.leaf) {
987            if std::ptr::eq(f, b) && fi >= bi {
988                self.exhausted = true;
989                return fi == bi && other_side_yielded;
990            }
991        }
992        false
993    }
994
995    #[cold]
996    fn peek_initial(&mut self, fwd: bool) -> Option<&'a (K, V)> {
997        debug_assert!(!self.exhausted);
998        let cursor = if fwd {
999            self.fwd_yielded = true;
1000            &mut self.fwd
1001        } else {
1002            self.bwd_yielded = true;
1003            &mut self.bwd
1004        };
1005        // If the cursor is empty we need to initialize it and seek to the first/last element.
1006        // If they were empty because exhaustion we would not be in this function.
1007        if cursor.is_empty() {
1008            cursor.init(self.root);
1009            if fwd {
1010                cursor.seek_to_first();
1011            } else {
1012                cursor.seek_to_last();
1013            }
1014        }
1015        cursor.peek()
1016    }
1017}
1018
1019impl<'a, K, V, P: SharedPointerKind> Iterator for Iter<'a, K, V, P> {
1020    type Item = (&'a K, &'a V);
1021
1022    fn next(&mut self) -> Option<Self::Item> {
1023        if self.exhausted {
1024            return None;
1025        }
1026        let next = if self.fwd_yielded {
1027            self.fwd.next()
1028        } else {
1029            self.peek_initial(true)
1030        }
1031        .map(|(k, v)| (k, v));
1032        if self.update_exhausted(next.is_some(), self.bwd_yielded) {
1033            return None;
1034        }
1035        self.remaining -= 1;
1036        next
1037    }
1038
1039    fn size_hint(&self) -> (usize, Option<usize>) {
1040        if self.exhausted {
1041            return (0, Some(0));
1042        }
1043        let lb = if self.exact { self.remaining } else { 0 };
1044        (lb, Some(self.remaining))
1045    }
1046}
1047
1048impl<'a, K, V, P: SharedPointerKind> DoubleEndedIterator for Iter<'a, K, V, P> {
1049    fn next_back(&mut self) -> Option<Self::Item> {
1050        if self.exhausted {
1051            return None;
1052        }
1053        let next = if self.bwd_yielded {
1054            self.bwd.prev()
1055        } else {
1056            self.peek_initial(false)
1057        }
1058        .map(|(k, v)| (k, v));
1059        if self.update_exhausted(next.is_some(), self.fwd_yielded) {
1060            return None;
1061        }
1062        self.remaining -= 1;
1063        next
1064    }
1065}
1066
1067impl<'a, K, V, P: SharedPointerKind> Clone for Iter<'a, K, V, P> {
1068    fn clone(&self) -> Self {
1069        Self {
1070            fwd: self.fwd.clone(),
1071            bwd: self.bwd.clone(),
1072            exact: self.exact,
1073            fwd_yielded: self.fwd_yielded,
1074            bwd_yielded: self.bwd_yielded,
1075            exhausted: self.exhausted,
1076            remaining: self.remaining,
1077            root: self.root,
1078        }
1079    }
1080}
1081
1082#[derive(Debug)]
1083pub(crate) struct Cursor<'a, K, V, P: SharedPointerKind> {
1084    // a sequence of nodes starting at the root
1085    stack: Vec<(usize, &'a Branch<K, V, P>)>,
1086    leaf: Option<(usize, &'a Leaf<K, V>)>,
1087}
1088
1089impl<'a, K, V, P: SharedPointerKind> Clone for Cursor<'a, K, V, P> {
1090    fn clone(&self) -> Self {
1091        Self {
1092            stack: self.stack.clone(),
1093            leaf: self.leaf,
1094        }
1095    }
1096}
1097
1098impl<'a, K, V, P: SharedPointerKind> Cursor<'a, K, V, P> {
1099    /// Creates a new empty cursor.
1100    /// The variety of methods is to allow for a more efficient initialization
1101    /// in all cases.
1102    pub(crate) fn empty() -> Self {
1103        Self {
1104            stack: Vec::new(),
1105            leaf: None,
1106        }
1107    }
1108
1109    fn is_empty(&self) -> bool {
1110        self.stack.is_empty() && self.leaf.is_none()
1111    }
1112
1113    pub(crate) fn init(&mut self, node: Option<&'a Node<K, V, P>>) {
1114        if let Some(node) = node {
1115            self.stack.reserve_exact(node.level());
1116            match node {
1117                Node::Branch(branch) => self.stack.push((0, branch)),
1118                Node::Leaf(leaf) => {
1119                    debug_assert!(self.leaf.is_none());
1120                    self.leaf = Some((0, leaf))
1121                }
1122            }
1123        }
1124    }
1125
1126    // pushes the `ix`th child of `branch` onto the stack, whether it's a leaf
1127    // or a branch
1128    fn push_child(&mut self, branch: &'a Branch<K, V, P>, ix: usize) {
1129        debug_assert!(
1130            self.leaf.is_none(),
1131            "it doesn't make sense to push when we're already at a leaf"
1132        );
1133        match &branch.children {
1134            Children::Leaves { leaves } => self.leaf = Some((0, &leaves[ix])),
1135            Children::Branches { branches, .. } => self.stack.push((0, &branches[ix])),
1136        }
1137    }
1138
1139    pub(crate) fn seek_to_first(&mut self) -> Option<&'a (K, V)> {
1140        loop {
1141            if let Some((i, leaf)) = &self.leaf {
1142                debug_assert_eq!(i, &0);
1143                return leaf.keys.first();
1144            }
1145            let (i, branch) = self.stack.last()?;
1146            debug_assert_eq!(i, &0);
1147            self.push_child(branch, 0);
1148        }
1149    }
1150
1151    fn seek_to_last(&mut self) -> Option<&'a (K, V)> {
1152        loop {
1153            if let Some((i, leaf)) = &mut self.leaf {
1154                debug_assert_eq!(i, &0);
1155                *i = leaf.keys.len().saturating_sub(1);
1156                return leaf.keys.last();
1157            }
1158            let (i, branch) = self.stack.last_mut()?;
1159            debug_assert_eq!(i, &0);
1160            *i = branch.children.len() - 1;
1161            let (i, branch) = (*i, *branch);
1162            self.push_child(branch, i);
1163        }
1164    }
1165
1166    fn seek_to_key<BK>(&mut self, key: &BK, for_prev: bool) -> bool
1167    where
1168        BK: Ord + ?Sized,
1169        K: Borrow<BK>,
1170    {
1171        loop {
1172            if let Some((i, leaf)) = &mut self.leaf {
1173                let search = slice_ext::binary_search_by(&leaf.keys, |(k, _)| k.borrow().cmp(key));
1174                *i = search.unwrap_or_else(|x| x);
1175                if for_prev {
1176                    if search.is_err() {
1177                        self.prev();
1178                    }
1179                } else if search == Err(leaf.keys.len()) {
1180                    self.next();
1181                }
1182                return search.is_ok();
1183            }
1184            let Some((i, branch)) = self.stack.last_mut() else {
1185                return false;
1186            };
1187            *i = slice_ext::binary_search_by(&branch.keys, |k| k.borrow().cmp(key))
1188                .map(|x| x + 1)
1189                .unwrap_or_else(|x| x);
1190            let (i, branch) = (*i, *branch);
1191            self.push_child(branch, i);
1192        }
1193    }
1194
1195    /// Advances this and another cursor to their next position.
1196    /// While doing so skip all shared nodes between them.
1197    pub(crate) fn advance_skipping_shared<'b>(&mut self, other: &mut Cursor<'b, K, V, P>) {
1198        // The current implementation is not optimal as it will still visit many nodes unnecessarily
1199        // before skipping them. But it requires very little additional code.
1200        // Nevertheless it will still improve performance when there are shared nodes.
1201        loop {
1202            let mut skipped_any = false;
1203            debug_assert!(self.leaf.is_some());
1204            debug_assert!(other.leaf.is_some());
1205            if let (Some(this), Some(that)) = (self.leaf, other.leaf) {
1206                if std::ptr::eq(this.1, that.1) {
1207                    self.leaf = None;
1208                    other.leaf = None;
1209                    skipped_any = true;
1210                    let shared_levels = self
1211                        .stack
1212                        .iter()
1213                        .rev()
1214                        .zip(other.stack.iter().rev())
1215                        .take_while(|(this, that)| std::ptr::eq(this.1, that.1))
1216                        .count();
1217                    if shared_levels != 0 {
1218                        self.stack.drain(self.stack.len() - shared_levels..);
1219                        other.stack.drain(other.stack.len() - shared_levels..);
1220                    }
1221                }
1222            }
1223            self.next();
1224            other.next();
1225            if !skipped_any || self.leaf.is_none() {
1226                break;
1227            }
1228        }
1229    }
1230
1231    pub(crate) fn next(&mut self) -> Option<&'a (K, V)> {
1232        loop {
1233            if let Some((i, leaf)) = &mut self.leaf {
1234                if *i + 1 < leaf.keys.len() {
1235                    *i += 1;
1236                    return leaf.keys.get(*i);
1237                }
1238                self.leaf = None;
1239            }
1240            let Some((i, branch)) = self.stack.last_mut() else {
1241                break;
1242            };
1243            if *i + 1 < branch.children.len() {
1244                *i += 1;
1245                let (i, branch) = (*i, *branch);
1246                self.push_child(branch, i);
1247                break;
1248            }
1249            self.stack.pop();
1250        }
1251        self.seek_to_first()
1252    }
1253
1254    fn prev(&mut self) -> Option<&'a (K, V)> {
1255        loop {
1256            if let Some((i, leaf)) = &mut self.leaf {
1257                if *i > 0 {
1258                    *i -= 1;
1259                    return leaf.keys.get(*i);
1260                }
1261                self.leaf = None;
1262            }
1263            let Some((i, branch)) = self.stack.last_mut() else {
1264                break;
1265            };
1266            if *i > 0 {
1267                *i -= 1;
1268                let (i, branch) = (*i, *branch);
1269                self.push_child(branch, i);
1270                break;
1271            }
1272            self.stack.pop();
1273        }
1274        self.seek_to_last()
1275    }
1276
1277    pub(crate) fn peek(&self) -> Option<&'a (K, V)> {
1278        if let Some((i, leaf)) = &self.leaf {
1279            leaf.keys.get(*i)
1280        } else {
1281            None
1282        }
1283    }
1284}
1285
1286mod slice_ext {
1287    #[inline]
1288    #[allow(unsafe_code)]
1289    pub(super) fn binary_search_by<T, F>(slice: &[T], mut f: F) -> Result<usize, usize>
1290    where
1291        F: FnMut(&T) -> std::cmp::Ordering,
1292    {
1293        // Optimization: defer to std-lib if we think we're comparing integers, in which case
1294        // the stdlib implementation optimizes better using a fully branchless approach.
1295        // This branch is fully resolved at compile-time and will not incur any space or runtime overhead.
1296        // There is a mild assumption that the std-lib implementation will remain optimized for primitive types.
1297        if !std::mem::needs_drop::<T>() && std::mem::size_of::<T>() <= 16 {
1298            return slice.binary_search_by(f);
1299        }
1300
1301        // This binary search implementation will always perform the minimum number of
1302        // comparisons and also allows for early return from the search loop when the comparison
1303        // function returns `Equal`, which is best when the comparison function isn't trivial
1304        // (e.g. `memcmp` vs. integer comparison).
1305
1306        use std::cmp::Ordering::*;
1307        let mut low = 0;
1308        let mut high = slice.len();
1309        // Compared to the stdlib this implementation perform early return when the comparison
1310        // function returns Equal and will perform the optimal number of comparisons.
1311        // This is a tradeoff when the comparisons aren't cheap, as is the case
1312        // when the comparison is a memcmp of the field name and CRDT type.
1313        while low < high {
1314            // the midpoint is biased (truncated) towards low so it will always be less than high
1315            let mid = low + (high - low) / 2;
1316            // Safety: mid is always in bounds as low < high <= slice.len(); thus mid < slice.len()
1317            let cmp = f(unsafe { slice.get_unchecked(mid) });
1318            // TODO: Use select_unpredictable when min rustc_version >= 1.88
1319            // to guarantee conditional move optimization.
1320            // low can only get up to slice.len() as mid < slice.len()
1321            low = if cmp == Less { mid + 1 } else { low };
1322            high = if cmp == Greater { mid } else { high };
1323            if cmp == Equal {
1324                // Safety: same as above
1325                unsafe {
1326                    std::hint::assert_unchecked(mid < slice.len());
1327                }
1328                return Ok(mid);
1329            }
1330        }
1331        // Safety: see low assignment above
1332        unsafe {
1333            std::hint::assert_unchecked(low <= slice.len());
1334        }
1335        Err(low)
1336    }
1337}