1 use core::borrow::Borrow;
2 use core::cmp::Ordering;
3 use core::ops::{Bound, RangeBounds};
5 use super::node::{marker, ForceResult::*, Handle, NodeRef};
10 pub enum SearchBound<T> {
11 /// An inclusive bound to look for, just like `Bound::Included(T)`.
13 /// An exclusive bound to look for, just like `Bound::Excluded(T)`.
15 /// An unconditional inclusive bound, just like `Bound::Unbounded`.
17 /// An unconditional exclusive bound.
21 impl<T> SearchBound<T> {
22 pub fn from_range(range_bound: Bound<T>) -> Self {
24 Bound::Included(t) => Included(t),
25 Bound::Excluded(t) => Excluded(t),
26 Bound::Unbounded => AllIncluded,
31 pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
32 Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>),
33 GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>),
36 pub enum IndexResult {
41 impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
42 /// Looks up a given key in a (sub)tree headed by the node, recursively.
43 /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
44 /// returns a `GoDown` with the handle of the leaf edge where the key belongs.
46 /// The result is meaningful only if the tree is ordered by key, like the tree
47 /// in a `BTreeMap` is.
48 pub fn search_tree<Q: ?Sized>(
51 ) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
57 self = match self.search_node(key) {
58 Found(handle) => return Found(handle),
59 GoDown(handle) => match handle.force() {
60 Leaf(leaf) => return GoDown(leaf),
61 Internal(internal) => internal.descend(),
67 /// Descends to the nearest node where the edge matching the lower bound
68 /// of the range is different from the edge matching the upper bound, i.e.,
69 /// the nearest node that has at least one key contained in the range.
71 /// If found, returns an `Ok` with that node, the strictly ascending pair of
72 /// edge indices in the node delimiting the range, and the corresponding
73 /// pair of bounds for continuing the search in the child nodes, in case
74 /// the node is internal.
76 /// If not found, returns an `Err` with the leaf edge matching the entire
79 /// As a diagnostic service, panics if the range specifies impossible bounds.
81 /// The result is meaningful only if the tree is ordered by key.
82 pub fn search_tree_for_bifurcation<'r, Q: ?Sized, R>(
87 NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
93 Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
100 // Inlining these variables should be avoided. We assume the bounds reported by `range`
101 // remain the same, but an adversarial implementation could change between calls (#81138).
102 let (start, end) = (range.start_bound(), range.end_bound());
104 (Bound::Excluded(s), Bound::Excluded(e)) if s == e => {
105 panic!("range start and end are equal and excluded in BTreeMap")
107 (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e))
110 panic!("range start is greater than range end in BTreeMap")
114 let mut lower_bound = SearchBound::from_range(start);
115 let mut upper_bound = SearchBound::from_range(end);
117 let (lower_edge_idx, lower_child_bound) = self.find_lower_bound_index(lower_bound);
118 let (upper_edge_idx, upper_child_bound) =
119 unsafe { self.find_upper_bound_index(upper_bound, lower_edge_idx) };
120 if lower_edge_idx < upper_edge_idx {
129 debug_assert_eq!(lower_edge_idx, upper_edge_idx);
130 let common_edge = unsafe { Handle::new_edge(self, lower_edge_idx) };
131 match common_edge.force() {
132 Leaf(common_edge) => return Err(common_edge),
133 Internal(common_edge) => {
134 self = common_edge.descend();
135 lower_bound = lower_child_bound;
136 upper_bound = upper_child_bound;
142 /// Finds an edge in the node delimiting the lower bound of a range.
143 /// Also returns the lower bound to be used for continuing the search in
144 /// the matching child node, if `self` is an internal node.
146 /// The result is meaningful only if the tree is ordered by key.
147 pub fn find_lower_bound_edge<'r, Q>(
149 bound: SearchBound<&'r Q>,
150 ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
155 let (edge_idx, bound) = self.find_lower_bound_index(bound);
156 let edge = unsafe { Handle::new_edge(self, edge_idx) };
160 /// Clone of `find_lower_bound_edge` for the upper bound.
161 pub fn find_upper_bound_edge<'r, Q>(
163 bound: SearchBound<&'r Q>,
164 ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
169 let (edge_idx, bound) = unsafe { self.find_upper_bound_index(bound, 0) };
170 let edge = unsafe { Handle::new_edge(self, edge_idx) };
175 impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
176 /// Looks up a given key in the node, without recursion.
177 /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
178 /// returns a `GoDown` with the handle of the edge where the key might be found
179 /// (if the node is internal) or where the key can be inserted.
181 /// The result is meaningful only if the tree is ordered by key, like the tree
182 /// in a `BTreeMap` is.
183 pub fn search_node<Q: ?Sized>(self, key: &Q) -> SearchResult<BorrowType, K, V, Type, Type>
188 match unsafe { self.find_key_index(key, 0) } {
189 IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }),
190 IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }),
194 /// Returns either the KV index in the node at which the key (or an equivalent)
195 /// exists, or the edge index where the key belongs, starting from a particular index.
197 /// The result is meaningful only if the tree is ordered by key, like the tree
198 /// in a `BTreeMap` is.
201 /// `start_index` must be a valid edge index for the node.
202 unsafe fn find_key_index<Q: ?Sized>(&self, key: &Q, start_index: usize) -> IndexResult
207 let node = self.reborrow();
208 let keys = node.keys();
209 debug_assert!(start_index <= keys.len());
210 for (offset, k) in unsafe { keys.get_unchecked(start_index..) }.iter().enumerate() {
211 match key.cmp(k.borrow()) {
212 Ordering::Greater => {}
213 Ordering::Equal => return IndexResult::KV(start_index + offset),
214 Ordering::Less => return IndexResult::Edge(start_index + offset),
217 IndexResult::Edge(keys.len())
220 /// Finds an edge index in the node delimiting the lower bound of a range.
221 /// Also returns the lower bound to be used for continuing the search in
222 /// the matching child node, if `self` is an internal node.
224 /// The result is meaningful only if the tree is ordered by key.
225 fn find_lower_bound_index<'r, Q>(
227 bound: SearchBound<&'r Q>,
228 ) -> (usize, SearchBound<&'r Q>)
234 Included(key) => match unsafe { self.find_key_index(key, 0) } {
235 IndexResult::KV(idx) => (idx, AllExcluded),
236 IndexResult::Edge(idx) => (idx, bound),
238 Excluded(key) => match unsafe { self.find_key_index(key, 0) } {
239 IndexResult::KV(idx) => (idx + 1, AllIncluded),
240 IndexResult::Edge(idx) => (idx, bound),
242 AllIncluded => (0, AllIncluded),
243 AllExcluded => (self.len(), AllExcluded),
247 /// Mirror image of `find_lower_bound_index` for the upper bound,
248 /// with an additional parameter to skip part of the key array.
251 /// `start_index` must be a valid edge index for the node.
252 unsafe fn find_upper_bound_index<'r, Q>(
254 bound: SearchBound<&'r Q>,
256 ) -> (usize, SearchBound<&'r Q>)
262 Included(key) => match unsafe { self.find_key_index(key, start_index) } {
263 IndexResult::KV(idx) => (idx + 1, AllExcluded),
264 IndexResult::Edge(idx) => (idx, bound),
266 Excluded(key) => match unsafe { self.find_key_index(key, start_index) } {
267 IndexResult::KV(idx) => (idx, AllIncluded),
268 IndexResult::Edge(idx) => (idx, bound),
270 AllIncluded => (self.len(), AllIncluded),
271 AllExcluded => (start_index, AllExcluded),