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 ;
24use core:: cmp:: Ord ;
35use core:: ops:: RangeBounds ;
46
@@ -18,15 +20,18 @@ use core::ops::RangeBounds;
1820/// actually backed by a `HashMap`, with some additional tracking to ensure we can iterate over
1921/// keys in the order defined by [`Ord`].
2022#[ 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 > ,
2327}
2428
25- impl < K : Ord , V > IndexedMap < K , V > {
29+ impl < K : Clone + Hash + Ord , V > IndexedMap < K , V > {
2630 /// Constructs a new, empty map
2731 pub fn new ( ) -> Self {
2832 Self {
29- map : BTreeMap :: new ( ) ,
33+ map : HashMap :: new ( ) ,
34+ keys : BTreeSet :: new ( ) ,
3035 }
3136 }
3237
@@ -49,26 +54,37 @@ impl<K: Ord, V> IndexedMap<K, V> {
4954
5055 /// Removes the element with the given `key`, returning it, if one exists.
5156 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
5362 }
5463
5564 /// Inserts the given `key`/`value` pair into the map, returning the element that was
5665 /// previously stored at the given `key`, if one exists.
5766 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
5972 }
6073
6174 /// Returns an [`Entry`] for the given `key` in the map, allowing access to the value.
6275 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) => {
6578 Entry :: Vacant ( VacantEntry {
66- underlying_entry : entry
79+ underlying_entry : entry,
80+ key,
81+ keys : & mut self . keys ,
6782 } )
6883 } ,
69- btree_map :: Entry :: Occupied ( entry) => {
84+ hash_map :: Entry :: Occupied ( entry) => {
7085 Entry :: Occupied ( OccupiedEntry {
71- underlying_entry : entry
86+ underlying_entry : entry,
87+ keys : & mut self . keys ,
7288 } )
7389 }
7490 }
@@ -91,8 +107,11 @@ impl<K: Ord, V> IndexedMap<K, V> {
91107 }
92108
93109 /// 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+ }
96115 }
97116
98117 /// Returns the number of `key`/`value` pairs in the map
@@ -106,34 +125,53 @@ impl<K: Ord, V> IndexedMap<K, V> {
106125 }
107126}
108127
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+
109141/// 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 > ,
112146}
113147
114148/// 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 > ,
117152}
118153
119154/// A mutable reference to a position in the map. This can be used to reference, add, or update the
120155/// value at a fixed key.
121- pub enum Entry < ' a , K : Ord , V > {
156+ pub enum Entry < ' a , K : Hash + Ord , V > {
122157 Vacant ( VacantEntry < ' a , K , V > ) ,
123158 Occupied ( OccupiedEntry < ' a , K , V > ) ,
124159}
125160
126- impl < ' a , K : Ord , V > VacantEntry < ' a , K , V > {
161+ impl < ' a , K : Hash + Ord , V > VacantEntry < ' a , K , V > {
127162 /// Insert a value into the position described by this entry.
128163 pub fn insert ( self , value : V ) -> & ' a mut V {
164+ assert ! ( self . keys. insert( self . key) , "map and keys must be consistent" ) ;
129165 self . underlying_entry . insert ( value)
130166 }
131167}
132168
133- impl < ' a , K : Ord , V > OccupiedEntry < ' a , K , V > {
169+ impl < ' a , K : Hash + Ord , V > OccupiedEntry < ' a , K , V > {
134170 /// Remove the value at the position described by this entry.
135171 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
137175 }
138176
139177 /// Get a reference to the value at the position described by this entry.
0 commit comments