Skip to content

Commit 5a6240c

Browse files
committed
introduce the Comparable trait for btree internals
1 parent d198b85 commit 5a6240c

File tree

4 files changed

+75
-27
lines changed

4 files changed

+75
-27
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//! Complements to the [`core::cmp`] module
2+
3+
use core::borrow::Borrow;
4+
use core::cmp::Ordering;
5+
6+
/// Key equivalence trait.
7+
///
8+
/// This trait allows hash table lookup to be customized. It has one blanket
9+
/// implementation that uses the regular solution with `Borrow` and `Eq`, just
10+
/// like `HashMap` does, so that you can pass `&str` to lookup into a map with
11+
/// `String` keys and so on.
12+
///
13+
/// # Contract
14+
///
15+
/// The implementor **must** hash like `Q`, if it is hashable.
16+
pub(crate) trait Equivalent<Q: ?Sized> {
17+
// /// Compare self to `key` and return `true` if they are equal.
18+
// fn equivalent(&self, key: &Q) -> bool;
19+
}
20+
21+
impl<K: ?Sized, Q: ?Sized> Equivalent<Q> for K
22+
where
23+
K: Borrow<Q>,
24+
Q: Eq,
25+
{
26+
// #[inline]
27+
// fn equivalent(&self, key: &Q) -> bool {
28+
// PartialEq::eq(self.borrow(), key)
29+
// }
30+
}
31+
32+
/// Key ordering trait.
33+
///
34+
/// This trait allows ordered map lookup to be customized. It has one blanket
35+
/// implementation that uses the regular solution with `Borrow` and `Ord`, just
36+
/// like `BTreeMap` does, so that you can pass `&str` to lookup into a map with
37+
/// `String` keys and so on.
38+
pub(crate) trait Comparable<Q: ?Sized>: Equivalent<Q> {
39+
/// Compare self to `key` and return their ordering.
40+
fn compare(&self, key: &Q) -> Ordering;
41+
}
42+
43+
impl<K: ?Sized, Q: ?Sized> Comparable<Q> for K
44+
where
45+
K: Borrow<Q>,
46+
Q: Ord,
47+
{
48+
#[inline]
49+
fn compare(&self, key: &Q) -> Ordering {
50+
Ord::cmp(self.borrow(), key)
51+
}
52+
}

library/alloc/src/collections/btree/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod append;
22
mod borrow;
3+
mod cmp;
34
mod dedup_sorted_iter;
45
mod fix;
56
pub(super) mod map;

library/alloc/src/collections/btree/navigate.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use core::borrow::Borrow;
21
use core::ops::RangeBounds;
32
use core::{hint, ptr};
43

4+
use super::cmp::Comparable;
55
use super::node::ForceResult::*;
66
use super::node::{Handle, NodeRef, marker};
77
use super::search::SearchBound;
@@ -267,7 +267,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
267267
) -> LeafRange<BorrowType, K, V>
268268
where
269269
Q: Ord,
270-
K: Borrow<Q>,
270+
K: Comparable<Q>,
271271
R: RangeBounds<Q>,
272272
{
273273
match self.search_tree_for_bifurcation(&range) {
@@ -316,7 +316,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
316316
pub(super) fn range_search<Q, R>(self, range: R) -> LeafRange<marker::Immut<'a>, K, V>
317317
where
318318
Q: ?Sized + Ord,
319-
K: Borrow<Q>,
319+
K: Comparable<Q>,
320320
R: RangeBounds<Q>,
321321
{
322322
// SAFETY: our borrow type is immutable.
@@ -342,7 +342,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::ValMut<'a>, K, V, marker::LeafOrInternal>
342342
pub(super) fn range_search<Q, R>(self, range: R) -> LeafRange<marker::ValMut<'a>, K, V>
343343
where
344344
Q: ?Sized + Ord,
345-
K: Borrow<Q>,
345+
K: Comparable<Q>,
346346
R: RangeBounds<Q>,
347347
{
348348
unsafe { self.find_leaf_edges_spanning_range(range) }
@@ -746,8 +746,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
746746
mut bound: SearchBound<&Q>,
747747
) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>
748748
where
749-
Q: Ord,
750-
K: Borrow<Q>,
749+
K: Comparable<Q>,
751750
{
752751
let mut node = self;
753752
loop {
@@ -769,8 +768,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
769768
mut bound: SearchBound<&Q>,
770769
) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>
771770
where
772-
Q: Ord,
773-
K: Borrow<Q>,
771+
K: Comparable<Q>,
774772
{
775773
let mut node = self;
776774
loop {

library/alloc/src/collections/btree/search.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use core::borrow::Borrow;
21
use core::cmp::Ordering;
32
use core::ops::{Bound, RangeBounds};
43

54
use SearchBound::*;
65
use SearchResult::*;
76

7+
use super::cmp::Comparable;
88
use super::node::ForceResult::*;
99
use super::node::{Handle, NodeRef, marker};
1010

@@ -51,8 +51,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
5151
key: &Q,
5252
) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
5353
where
54-
Q: Ord,
55-
K: Borrow<Q>,
54+
K: Comparable<Q>,
5655
{
5756
loop {
5857
self = match self.search_node(key) {
@@ -95,7 +94,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
9594
>
9695
where
9796
Q: Ord,
98-
K: Borrow<Q>,
97+
K: Comparable<Q>,
9998
R: RangeBounds<Q>,
10099
{
101100
// Determine if map or set is being searched
@@ -161,8 +160,8 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
161160
bound: SearchBound<&'r Q>,
162161
) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
163162
where
164-
Q: ?Sized + Ord,
165-
K: Borrow<Q>,
163+
Q: ?Sized,
164+
K: Comparable<Q>,
166165
{
167166
let (edge_idx, bound) = self.find_lower_bound_index(bound);
168167
let edge = unsafe { Handle::new_edge(self, edge_idx) };
@@ -175,8 +174,8 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
175174
bound: SearchBound<&'r Q>,
176175
) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
177176
where
178-
Q: ?Sized + Ord,
179-
K: Borrow<Q>,
177+
Q: ?Sized,
178+
K: Comparable<Q>,
180179
{
181180
let (edge_idx, bound) = unsafe { self.find_upper_bound_index(bound, 0) };
182181
let edge = unsafe { Handle::new_edge(self, edge_idx) };
@@ -197,8 +196,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
197196
key: &Q,
198197
) -> SearchResult<BorrowType, K, V, Type, Type>
199198
where
200-
Q: Ord,
201-
K: Borrow<Q>,
199+
K: Comparable<Q>,
202200
{
203201
match unsafe { self.find_key_index(key, 0) } {
204202
IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }),
@@ -216,17 +214,16 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
216214
/// `start_index` must be a valid edge index for the node.
217215
unsafe fn find_key_index<Q: ?Sized>(&self, key: &Q, start_index: usize) -> IndexResult
218216
where
219-
Q: Ord,
220-
K: Borrow<Q>,
217+
K: Comparable<Q>,
221218
{
222219
let node = self.reborrow();
223220
let keys = node.keys();
224221
debug_assert!(start_index <= keys.len());
225222
for (offset, k) in unsafe { keys.get_unchecked(start_index..) }.iter().enumerate() {
226-
match key.cmp(k.borrow()) {
227-
Ordering::Greater => {}
223+
match k.compare(key) {
224+
Ordering::Less => {}
228225
Ordering::Equal => return IndexResult::KV(start_index + offset),
229-
Ordering::Less => return IndexResult::Edge(start_index + offset),
226+
Ordering::Greater => return IndexResult::Edge(start_index + offset),
230227
}
231228
}
232229
IndexResult::Edge(keys.len())
@@ -242,8 +239,8 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
242239
bound: SearchBound<&'r Q>,
243240
) -> (usize, SearchBound<&'r Q>)
244241
where
245-
Q: ?Sized + Ord,
246-
K: Borrow<Q>,
242+
Q: ?Sized,
243+
K: Comparable<Q>,
247244
{
248245
match bound {
249246
Included(key) => match unsafe { self.find_key_index(key, 0) } {
@@ -270,8 +267,8 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
270267
start_index: usize,
271268
) -> (usize, SearchBound<&'r Q>)
272269
where
273-
Q: ?Sized + Ord,
274-
K: Borrow<Q>,
270+
Q: ?Sized,
271+
K: Comparable<Q>,
275272
{
276273
match bound {
277274
Included(key) => match unsafe { self.find_key_index(key, start_index) } {

0 commit comments

Comments
 (0)