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