1
- use alloc:: collections:: { BTreeMap , btree_map} ;
1
+ use crate :: prelude:: { HashMap , hash_map} ;
2
+ use alloc:: collections:: { BTreeSet , btree_set} ;
3
+ use core:: hash:: Hash ;
2
4
use core:: cmp:: Ord ;
3
5
use core:: ops:: RangeBounds ;
4
6
@@ -18,15 +20,18 @@ use core::ops::RangeBounds;
18
20
/// actually backed by a `HashMap`, with some additional tracking to ensure we can iterate over
19
21
/// keys in the order defined by [`Ord`].
20
22
#[ derive( Clone , PartialEq , Eq ) ]
21
- pub struct IndexedMap < K : Ord , V > {
22
- map : BTreeMap < K , V > ,
23
+ pub struct IndexedMap < K : Hash + Ord , V > {
24
+ map : HashMap < K , V > ,
25
+ // TODO: Explore swapping this for a sorted vec (that is only sorted on first range() call)
26
+ keys : BTreeSet < K > ,
23
27
}
24
28
25
- impl < K : Ord , V > IndexedMap < K , V > {
29
+ impl < K : Clone + Hash + Ord , V > IndexedMap < K , V > {
26
30
/// Constructs a new, empty map
27
31
pub fn new ( ) -> Self {
28
32
Self {
29
- map : BTreeMap :: new ( ) ,
33
+ map : HashMap :: new ( ) ,
34
+ keys : BTreeSet :: new ( ) ,
30
35
}
31
36
}
32
37
@@ -49,26 +54,37 @@ impl<K: Ord, V> IndexedMap<K, V> {
49
54
50
55
/// Removes the element with the given `key`, returning it, if one exists.
51
56
pub fn remove ( & mut self , key : & K ) -> Option < V > {
52
- self . map . remove ( key)
57
+ let ret = self . map . remove ( key) ;
58
+ if let Some ( _) = ret {
59
+ assert ! ( self . keys. remove( key) , "map and keys must be consistent" ) ;
60
+ }
61
+ ret
53
62
}
54
63
55
64
/// Inserts the given `key`/`value` pair into the map, returning the element that was
56
65
/// previously stored at the given `key`, if one exists.
57
66
pub fn insert ( & mut self , key : K , value : V ) -> Option < V > {
58
- self . map . insert ( key, value)
67
+ let ret = self . map . insert ( key. clone ( ) , value) ;
68
+ if ret. is_none ( ) {
69
+ assert ! ( self . keys. insert( key) , "map and keys must be consistent" ) ;
70
+ }
71
+ ret
59
72
}
60
73
61
74
/// Returns an [`Entry`] for the given `key` in the map, allowing access to the value.
62
75
pub fn entry ( & mut self , key : K ) -> Entry < ' _ , K , V > {
63
- match self . map . entry ( key) {
64
- btree_map :: Entry :: Vacant ( entry) => {
76
+ match self . map . entry ( key. clone ( ) ) {
77
+ hash_map :: Entry :: Vacant ( entry) => {
65
78
Entry :: Vacant ( VacantEntry {
66
- underlying_entry : entry
79
+ underlying_entry : entry,
80
+ key,
81
+ keys : & mut self . keys ,
67
82
} )
68
83
} ,
69
- btree_map :: Entry :: Occupied ( entry) => {
84
+ hash_map :: Entry :: Occupied ( entry) => {
70
85
Entry :: Occupied ( OccupiedEntry {
71
- underlying_entry : entry
86
+ underlying_entry : entry,
87
+ keys : & mut self . keys ,
72
88
} )
73
89
}
74
90
}
@@ -91,8 +107,11 @@ impl<K: Ord, V> IndexedMap<K, V> {
91
107
}
92
108
93
109
/// Returns an iterator which iterates over the `key`/`value` pairs in a given range.
94
- pub fn range < R : RangeBounds < K > > ( & self , range : R ) -> btree_map:: Range < K , V > {
95
- self . map . range ( range)
110
+ pub fn range < R : RangeBounds < K > > ( & self , range : R ) -> Range < K , V > {
111
+ Range {
112
+ inner_range : self . keys . range ( range) ,
113
+ map : & self . map ,
114
+ }
96
115
}
97
116
98
117
/// Returns the number of `key`/`value` pairs in the map
@@ -106,34 +125,53 @@ impl<K: Ord, V> IndexedMap<K, V> {
106
125
}
107
126
}
108
127
128
+ pub struct Range < ' a , K : Hash + Ord , V > {
129
+ inner_range : btree_set:: Range < ' a , K > ,
130
+ map : & ' a HashMap < K , V > ,
131
+ }
132
+ impl < ' a , K : Hash + Ord , V : ' a > Iterator for Range < ' a , K , V > {
133
+ type Item = ( & ' a K , & ' a V ) ;
134
+ fn next ( & mut self ) -> Option < ( & ' a K , & ' a V ) > {
135
+ self . inner_range . next ( ) . map ( |k| {
136
+ ( k, self . map . get ( k) . expect ( "map and keys must be consistent" ) )
137
+ } )
138
+ }
139
+ }
140
+
109
141
/// An [`Entry`] for a key which currently has no value
110
- pub struct VacantEntry < ' a , K : Ord , V > {
111
- underlying_entry : btree_map:: VacantEntry < ' a , K , V > ,
142
+ pub struct VacantEntry < ' a , K : Hash + Ord , V > {
143
+ underlying_entry : hash_map:: VacantEntry < ' a , K , V > ,
144
+ key : K ,
145
+ keys : & ' a mut BTreeSet < K > ,
112
146
}
113
147
114
148
/// An [`Entry`] for an existing key-value pair
115
- pub struct OccupiedEntry < ' a , K : Ord , V > {
116
- underlying_entry : btree_map:: OccupiedEntry < ' a , K , V > ,
149
+ pub struct OccupiedEntry < ' a , K : Hash + Ord , V > {
150
+ underlying_entry : hash_map:: OccupiedEntry < ' a , K , V > ,
151
+ keys : & ' a mut BTreeSet < K > ,
117
152
}
118
153
119
154
/// A mutable reference to a position in the map. This can be used to reference, add, or update the
120
155
/// value at a fixed key.
121
- pub enum Entry < ' a , K : Ord , V > {
156
+ pub enum Entry < ' a , K : Hash + Ord , V > {
122
157
Vacant ( VacantEntry < ' a , K , V > ) ,
123
158
Occupied ( OccupiedEntry < ' a , K , V > ) ,
124
159
}
125
160
126
- impl < ' a , K : Ord , V > VacantEntry < ' a , K , V > {
161
+ impl < ' a , K : Hash + Ord , V > VacantEntry < ' a , K , V > {
127
162
/// Insert a value into the position described by this entry.
128
163
pub fn insert ( self , value : V ) -> & ' a mut V {
164
+ assert ! ( self . keys. insert( self . key) , "map and keys must be consistent" ) ;
129
165
self . underlying_entry . insert ( value)
130
166
}
131
167
}
132
168
133
- impl < ' a , K : Ord , V > OccupiedEntry < ' a , K , V > {
169
+ impl < ' a , K : Hash + Ord , V > OccupiedEntry < ' a , K , V > {
134
170
/// Remove the value at the position described by this entry.
135
171
pub fn remove_entry ( self ) -> ( K , V ) {
136
- self . underlying_entry . remove_entry ( )
172
+ let res = self . underlying_entry . remove_entry ( ) ;
173
+ assert ! ( self . keys. remove( & res. 0 ) , "map and keys must be consistent" ) ;
174
+ res
137
175
}
138
176
139
177
/// Get a reference to the value at the position described by this entry.
0 commit comments