1
1
use core:: borrow:: Borrow ;
2
- use core:: cmp:: Ordering ;
3
- use core:: ops:: Bound :: { Excluded , Included , Unbounded } ;
4
2
use core:: ops:: RangeBounds ;
5
3
use core:: ptr;
6
4
7
5
use super :: node:: { marker, ForceResult :: * , Handle , NodeRef } ;
8
- use super :: search:: SearchResult ;
9
6
10
7
pub struct LeafRange < BorrowType , K , V > {
11
8
pub front : Option < Handle < NodeRef < BorrowType , K , V , marker:: Leaf > , marker:: Edge > > ,
@@ -30,100 +27,50 @@ impl<BorrowType, K, V> LeafRange<BorrowType, K, V> {
30
27
}
31
28
}
32
29
33
- /// Finds the leaf edges delimiting a specified range in or underneath a node.
34
- ///
35
- /// The result is meaningful only if the tree is ordered by key, like the tree
36
- /// in a `BTreeMap` is.
37
- fn range_search < BorrowType : marker:: BorrowType , K , V , Q , R > (
38
- root1 : NodeRef < BorrowType , K , V , marker:: LeafOrInternal > ,
39
- root2 : NodeRef < BorrowType , K , V , marker:: LeafOrInternal > ,
40
- range : R ,
41
- ) -> LeafRange < BorrowType , K , V >
42
- where
43
- Q : ?Sized + Ord ,
44
- K : Borrow < Q > ,
45
- R : RangeBounds < Q > ,
46
- {
47
- // WARNING: Inlining these variables would be unsound (#81138)
48
- // We assume the bounds reported by `range` remain the same, but
49
- // an adversarial implementation could change between calls
50
- let start = range. start_bound ( ) ;
51
- let end = range. end_bound ( ) ;
52
- match ( start, end) {
53
- ( Excluded ( s) , Excluded ( e) ) if s == e => {
54
- panic ! ( "range start and end are equal and excluded in BTreeMap" )
55
- }
56
- ( Included ( s) | Excluded ( s) , Included ( e) | Excluded ( e) ) if s > e => {
57
- panic ! ( "range start is greater than range end in BTreeMap" )
58
- }
59
- _ => { }
60
- } ;
61
-
62
- let mut min_node = root1;
63
- let mut max_node = root2;
64
- let mut min_found = false ;
65
- let mut max_found = false ;
66
-
67
- loop {
68
- // Using `range` again would be unsound (#81138)
69
- let front = match ( min_found, start) {
70
- ( false , Included ( key) ) => match min_node. search_node ( key) {
71
- SearchResult :: Found ( kv) => {
72
- min_found = true ;
73
- kv. left_edge ( )
74
- }
75
- SearchResult :: GoDown ( edge) => edge,
76
- } ,
77
- ( false , Excluded ( key) ) => match min_node. search_node ( key) {
78
- SearchResult :: Found ( kv) => {
79
- min_found = true ;
80
- kv. right_edge ( )
81
- }
82
- SearchResult :: GoDown ( edge) => edge,
83
- } ,
84
- ( true , Included ( _) ) => min_node. last_edge ( ) ,
85
- ( true , Excluded ( _) ) => min_node. first_edge ( ) ,
86
- ( _, Unbounded ) => min_node. first_edge ( ) ,
87
- } ;
88
-
89
- // Using `range` again would be unsound (#81138)
90
- let back = match ( max_found, end) {
91
- ( false , Included ( key) ) => match max_node. search_node ( key) {
92
- SearchResult :: Found ( kv) => {
93
- max_found = true ;
94
- kv. right_edge ( )
95
- }
96
- SearchResult :: GoDown ( edge) => edge,
97
- } ,
98
- ( false , Excluded ( key) ) => match max_node. search_node ( key) {
99
- SearchResult :: Found ( kv) => {
100
- max_found = true ;
101
- kv. left_edge ( )
30
+ impl < BorrowType : marker:: BorrowType , K , V > NodeRef < BorrowType , K , V , marker:: LeafOrInternal > {
31
+ /// Finds the distinct leaf edges delimiting a specified range in a tree.
32
+ /// Returns either a pair of different handles into the same tree or a pair
33
+ /// of empty options.
34
+ /// # Safety
35
+ /// Unless `BorrowType` is `Immut`, do not use the duplicate handles to
36
+ /// visit the same KV twice.
37
+ unsafe fn find_leaf_edges_spanning_range < Q : ?Sized , R > (
38
+ self ,
39
+ range : R ,
40
+ ) -> LeafRange < BorrowType , K , V >
41
+ where
42
+ Q : Ord ,
43
+ K : Borrow < Q > ,
44
+ R : RangeBounds < Q > ,
45
+ {
46
+ match self . search_tree_for_bifurcation ( & range) {
47
+ Err ( _) => LeafRange :: none ( ) ,
48
+ Ok ( (
49
+ node,
50
+ lower_edge_idx,
51
+ upper_edge_idx,
52
+ mut lower_child_bound,
53
+ mut upper_child_bound,
54
+ ) ) => {
55
+ let mut lower_edge = unsafe { Handle :: new_edge ( ptr:: read ( & node) , lower_edge_idx) } ;
56
+ let mut upper_edge = unsafe { Handle :: new_edge ( node, upper_edge_idx) } ;
57
+ loop {
58
+ match ( lower_edge. force ( ) , upper_edge. force ( ) ) {
59
+ ( Leaf ( f) , Leaf ( b) ) => return LeafRange { front : Some ( f) , back : Some ( b) } ,
60
+ ( Internal ( f) , Internal ( b) ) => {
61
+ ( lower_edge, lower_child_bound) =
62
+ f. descend ( ) . find_lower_bound_edge ( lower_child_bound) ;
63
+ ( upper_edge, upper_child_bound) =
64
+ b. descend ( ) . find_upper_bound_edge ( upper_child_bound) ;
65
+ }
66
+ _ => unreachable ! ( "BTreeMap has different depths" ) ,
67
+ }
102
68
}
103
- SearchResult :: GoDown ( edge) => edge,
104
- } ,
105
- ( true , Included ( _) ) => max_node. first_edge ( ) ,
106
- ( true , Excluded ( _) ) => max_node. last_edge ( ) ,
107
- ( _, Unbounded ) => max_node. last_edge ( ) ,
108
- } ;
109
-
110
- if front. partial_cmp ( & back) == Some ( Ordering :: Greater ) {
111
- panic ! ( "Ord is ill-defined in BTreeMap range" ) ;
112
- }
113
- match ( front. force ( ) , back. force ( ) ) {
114
- ( Leaf ( f) , Leaf ( b) ) => {
115
- return LeafRange { front : Some ( f) , back : Some ( b) } ;
116
69
}
117
- ( Internal ( min_int) , Internal ( max_int) ) => {
118
- min_node = min_int. descend ( ) ;
119
- max_node = max_int. descend ( ) ;
120
- }
121
- _ => unreachable ! ( "BTreeMap has different depths" ) ,
122
- } ;
70
+ }
123
71
}
124
72
}
125
73
126
- /// Equivalent to `range_search(root1, root2, ..)` but without the `Ord` bound.
127
74
/// Equivalent to `(root1.first_leaf_edge(), root2.last_leaf_edge())` but more efficient.
128
75
fn full_range < BorrowType : marker:: BorrowType , K , V > (
129
76
root1 : NodeRef < BorrowType , K , V , marker:: LeafOrInternal > ,
@@ -158,7 +105,8 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
158
105
K : Borrow < Q > ,
159
106
R : RangeBounds < Q > ,
160
107
{
161
- range_search ( self , self , range)
108
+ // SAFETY: our borrow type is immutable.
109
+ unsafe { self . find_leaf_edges_spanning_range ( range) }
162
110
}
163
111
164
112
/// Finds the pair of leaf edges delimiting an entire tree.
@@ -174,16 +122,16 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::ValMut<'a>, K, V, marker::LeafOrInternal>
174
122
///
175
123
/// The result is meaningful only if the tree is ordered by key, like the tree
176
124
/// in a `BTreeMap` is.
125
+ ///
126
+ /// # Safety
127
+ /// Do not use the duplicate handles to visit the same KV twice.
177
128
pub fn range_search < Q , R > ( self , range : R ) -> LeafRange < marker:: ValMut < ' a > , K , V >
178
129
where
179
130
Q : ?Sized + Ord ,
180
131
K : Borrow < Q > ,
181
132
R : RangeBounds < Q > ,
182
133
{
183
- // We duplicate the root NodeRef here -- we will never visit the same KV
184
- // twice, and never end up with overlapping value references.
185
- let self2 = unsafe { ptr:: read ( & self ) } ;
186
- range_search ( self , self2, range)
134
+ unsafe { self . find_leaf_edges_spanning_range ( range) }
187
135
}
188
136
189
137
/// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree.
0 commit comments