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