11use core:: borrow:: Borrow ;
2- use core:: cmp:: Ordering ;
3- use core:: ops:: Bound :: { Excluded , Included , Unbounded } ;
42use core:: ops:: RangeBounds ;
53use core:: ptr;
64
75use super :: node:: { marker, ForceResult :: * , Handle , NodeRef } ;
8- use super :: search:: SearchResult ;
96
107pub struct LeafRange < BorrowType , K , V > {
118 pub front : Option < Handle < NodeRef < BorrowType , K , V , marker:: Leaf > , marker:: Edge > > ,
@@ -30,100 +27,50 @@ impl<BorrowType, K, V> LeafRange<BorrowType, K, V> {
3027 }
3128}
3229
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+ }
10268 }
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) } ;
11669 }
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+ }
12371 }
12472}
12573
126- /// Equivalent to `range_search(root1, root2, ..)` but without the `Ord` bound.
12774/// Equivalent to `(root1.first_leaf_edge(), root2.last_leaf_edge())` but more efficient.
12875fn full_range < BorrowType : marker:: BorrowType , K , V > (
12976 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>
158105 K : Borrow < Q > ,
159106 R : RangeBounds < Q > ,
160107 {
161- range_search ( self , self , range)
108+ // SAFETY: our borrow type is immutable.
109+ unsafe { self . find_leaf_edges_spanning_range ( range) }
162110 }
163111
164112 /// 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>
174122 ///
175123 /// The result is meaningful only if the tree is ordered by key, like the tree
176124 /// in a `BTreeMap` is.
125+ ///
126+ /// # Safety
127+ /// Do not use the duplicate handles to visit the same KV twice.
177128 pub fn range_search < Q , R > ( self , range : R ) -> LeafRange < marker:: ValMut < ' a > , K , V >
178129 where
179130 Q : ?Sized + Ord ,
180131 K : Borrow < Q > ,
181132 R : RangeBounds < Q > ,
182133 {
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) }
187135 }
188136
189137 /// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree.
0 commit comments