@@ -68,13 +68,16 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
68
68
/// of the range is different from the edge matching the upper bound, i.e.,
69
69
/// the nearest node that has at least one key contained in the range.
70
70
///
71
- /// If found, returns an `Ok` with that node, the pair of edge indices in it
72
- /// delimiting the range, and the corresponding pair of bounds for
73
- /// continuing the search in the child nodes, in case the node is internal.
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.
74
75
///
75
76
/// If not found, returns an `Err` with the leaf edge matching the entire
76
77
/// range.
77
78
///
79
+ /// As a diagnostic service, panics if the range specifies impossible bounds.
80
+ ///
78
81
/// The result is meaningful only if the tree is ordered by key.
79
82
pub fn search_tree_for_bifurcation < ' r , Q : ?Sized , R > (
80
83
mut self ,
@@ -112,10 +115,8 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
112
115
let mut upper_bound = SearchBound :: from_range ( end) ;
113
116
loop {
114
117
let ( lower_edge_idx, lower_child_bound) = self . find_lower_bound_index ( lower_bound) ;
115
- let ( upper_edge_idx, upper_child_bound) = self . find_upper_bound_index ( upper_bound) ;
116
- if lower_edge_idx > upper_edge_idx {
117
- panic ! ( "Ord is ill-defined in BTreeMap range" )
118
- }
118
+ let ( upper_edge_idx, upper_child_bound) =
119
+ unsafe { self . find_upper_bound_index ( upper_bound, lower_edge_idx) } ;
119
120
if lower_edge_idx < upper_edge_idx {
120
121
return Ok ( (
121
122
self ,
@@ -125,6 +126,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
125
126
upper_child_bound,
126
127
) ) ;
127
128
}
129
+ debug_assert_eq ! ( lower_edge_idx, upper_edge_idx) ;
128
130
let common_edge = unsafe { Handle :: new_edge ( self , lower_edge_idx) } ;
129
131
match common_edge. force ( ) {
130
132
Leaf ( common_edge) => return Err ( common_edge) ,
@@ -164,7 +166,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
164
166
Q : ?Sized + Ord ,
165
167
K : Borrow < Q > ,
166
168
{
167
- let ( edge_idx, bound) = self . find_upper_bound_index ( bound) ;
169
+ let ( edge_idx, bound) = unsafe { self . find_upper_bound_index ( bound, 0 ) } ;
168
170
let edge = unsafe { Handle :: new_edge ( self , edge_idx) } ;
169
171
( edge, bound)
170
172
}
@@ -183,29 +185,33 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
183
185
Q : Ord ,
184
186
K : Borrow < Q > ,
185
187
{
186
- match self . find_key_index ( key) {
188
+ match unsafe { self . find_key_index ( key, 0 ) } {
187
189
IndexResult :: KV ( idx) => Found ( unsafe { Handle :: new_kv ( self , idx) } ) ,
188
190
IndexResult :: Edge ( idx) => GoDown ( unsafe { Handle :: new_edge ( self , idx) } ) ,
189
191
}
190
192
}
191
193
192
194
/// Returns either the KV index in the node at which the key (or an equivalent)
193
- /// exists, or the edge index where the key belongs.
195
+ /// exists, or the edge index where the key belongs, starting from a particular index .
194
196
///
195
197
/// The result is meaningful only if the tree is ordered by key, like the tree
196
198
/// in a `BTreeMap` is.
197
- fn find_key_index < Q : ?Sized > ( & self , key : & Q ) -> IndexResult
199
+ ///
200
+ /// # Safety
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
198
203
where
199
204
Q : Ord ,
200
205
K : Borrow < Q > ,
201
206
{
202
207
let node = self . reborrow ( ) ;
203
208
let keys = node. keys ( ) ;
204
- for ( i, k) in keys. iter ( ) . enumerate ( ) {
209
+ debug_assert ! ( start_index <= keys. len( ) ) ;
210
+ for ( offset, k) in unsafe { keys. get_unchecked ( start_index..) } . iter ( ) . enumerate ( ) {
205
211
match key. cmp ( k. borrow ( ) ) {
206
212
Ordering :: Greater => { }
207
- Ordering :: Equal => return IndexResult :: KV ( i ) ,
208
- Ordering :: Less => return IndexResult :: Edge ( i ) ,
213
+ Ordering :: Equal => return IndexResult :: KV ( start_index + offset ) ,
214
+ Ordering :: Less => return IndexResult :: Edge ( start_index + offset ) ,
209
215
}
210
216
}
211
217
IndexResult :: Edge ( keys. len ( ) )
@@ -225,11 +231,11 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
225
231
K : Borrow < Q > ,
226
232
{
227
233
match bound {
228
- Included ( key) => match self . find_key_index ( key) {
234
+ Included ( key) => match unsafe { self . find_key_index ( key, 0 ) } {
229
235
IndexResult :: KV ( idx) => ( idx, AllExcluded ) ,
230
236
IndexResult :: Edge ( idx) => ( idx, bound) ,
231
237
} ,
232
- Excluded ( key) => match self . find_key_index ( key) {
238
+ Excluded ( key) => match unsafe { self . find_key_index ( key, 0 ) } {
233
239
IndexResult :: KV ( idx) => ( idx + 1 , AllIncluded ) ,
234
240
IndexResult :: Edge ( idx) => ( idx, bound) ,
235
241
} ,
@@ -238,26 +244,31 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
238
244
}
239
245
}
240
246
241
- /// Clone of `find_lower_bound_index` for the upper bound.
242
- fn find_upper_bound_index < ' r , Q > (
247
+ /// Mirror image of `find_lower_bound_index` for the upper bound,
248
+ /// with an additional parameter to skip part of the key array.
249
+ ///
250
+ /// # Safety
251
+ /// `start_index` must be a valid edge index for the node.
252
+ unsafe fn find_upper_bound_index < ' r , Q > (
243
253
& self ,
244
254
bound : SearchBound < & ' r Q > ,
255
+ start_index : usize ,
245
256
) -> ( usize , SearchBound < & ' r Q > )
246
257
where
247
258
Q : ?Sized + Ord ,
248
259
K : Borrow < Q > ,
249
260
{
250
261
match bound {
251
- Included ( key) => match self . find_key_index ( key) {
262
+ Included ( key) => match unsafe { self . find_key_index ( key, start_index ) } {
252
263
IndexResult :: KV ( idx) => ( idx + 1 , AllExcluded ) ,
253
264
IndexResult :: Edge ( idx) => ( idx, bound) ,
254
265
} ,
255
- Excluded ( key) => match self . find_key_index ( key) {
266
+ Excluded ( key) => match unsafe { self . find_key_index ( key, start_index ) } {
256
267
IndexResult :: KV ( idx) => ( idx, AllIncluded ) ,
257
268
IndexResult :: Edge ( idx) => ( idx, bound) ,
258
269
} ,
259
270
AllIncluded => ( self . len ( ) , AllIncluded ) ,
260
- AllExcluded => ( 0 , AllExcluded ) ,
271
+ AllExcluded => ( start_index , AllExcluded ) ,
261
272
}
262
273
}
263
274
}
0 commit comments