11//! This module has a map which can be iterated in a deterministic order. See the [`IndexedMap`].
22
33use crate :: prelude:: { HashMap , hash_map} ;
4- use alloc:: collections:: { BTreeSet , btree_set} ;
4+ use alloc:: vec:: Vec ;
5+ use alloc:: slice:: Iter ;
56use core:: hash:: Hash ;
67use core:: cmp:: Ord ;
7- use core:: ops:: RangeBounds ;
8+ use core:: ops:: { Bound , RangeBounds } ;
89
910/// A map which can be iterated in a deterministic order.
1011///
@@ -21,19 +22,18 @@ use core::ops::RangeBounds;
2122/// keys in the order defined by [`Ord`].
2223///
2324/// [`BTreeMap`]: alloc::collections::BTreeMap
24- #[ derive( Clone , Debug , PartialEq , Eq ) ]
25+ #[ derive( Clone , Debug , Eq ) ]
2526pub struct IndexedMap < K : Hash + Ord , V > {
2627 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 > ,
28+ keys : Vec < K > ,
2929}
3030
3131impl < K : Clone + Hash + Ord , V > IndexedMap < K , V > {
3232 /// Constructs a new, empty map
3333 pub fn new ( ) -> Self {
3434 Self {
3535 map : HashMap :: new ( ) ,
36- keys : BTreeSet :: new ( ) ,
36+ keys : Vec :: new ( ) ,
3737 }
3838 }
3939
@@ -58,7 +58,8 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
5858 pub fn remove ( & mut self , key : & K ) -> Option < V > {
5959 let ret = self . map . remove ( key) ;
6060 if let Some ( _) = ret {
61- assert ! ( self . keys. remove( key) , "map and keys must be consistent" ) ;
61+ let idx = self . keys . iter ( ) . position ( |k| k == key) . expect ( "map and keys must be consistent" ) ;
62+ self . keys . remove ( idx) ;
6263 }
6364 ret
6465 }
@@ -68,7 +69,7 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
6869 pub fn insert ( & mut self , key : K , value : V ) -> Option < V > {
6970 let ret = self . map . insert ( key. clone ( ) , value) ;
7071 if ret. is_none ( ) {
71- assert ! ( self . keys. insert ( key) , "map and keys must be consistent" ) ;
72+ self . keys . push ( key) ;
7273 }
7374 ret
7475 }
@@ -109,9 +110,21 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
109110 }
110111
111112 /// Returns an iterator which iterates over the `key`/`value` pairs in a given range.
112- pub fn range < R : RangeBounds < K > > ( & self , range : R ) -> Range < K , V > {
113+ pub fn range < R : RangeBounds < K > > ( & mut self , range : R ) -> Range < K , V > {
114+ self . keys . sort ( ) ;
115+ let start = match range. start_bound ( ) {
116+ Bound :: Unbounded => 0 ,
117+ Bound :: Included ( key) => self . keys . binary_search ( key) . unwrap_or_else ( |index| index) ,
118+ Bound :: Excluded ( key) => self . keys . binary_search ( key) . and_then ( |index| Ok ( index + 1 ) ) . unwrap_or_else ( |index| index) ,
119+ } ;
120+ let end = match range. end_bound ( ) {
121+ Bound :: Unbounded => self . keys . len ( ) ,
122+ Bound :: Included ( key) => self . keys . binary_search ( key) . and_then ( |index| Ok ( index + 1 ) ) . unwrap_or_else ( |index| index) ,
123+ Bound :: Excluded ( key) => self . keys . binary_search ( key) . unwrap_or_else ( |index| index) ,
124+ } ;
125+
113126 Range {
114- inner_range : self . keys . range ( range ) ,
127+ inner_range : self . keys [ start..end ] . iter ( ) ,
115128 map : & self . map ,
116129 }
117130 }
@@ -127,9 +140,15 @@ impl<K: Clone + Hash + Ord, V> IndexedMap<K, V> {
127140 }
128141}
129142
143+ impl < K : Hash + Ord + PartialEq , V : PartialEq > PartialEq for IndexedMap < K , V > {
144+ fn eq ( & self , other : & Self ) -> bool {
145+ self . map == other. map && self . keys . iter ( ) . all ( |item| self . keys . contains ( item) )
146+ }
147+ }
148+
130149/// An iterator over a range of values in an [`IndexedMap`]
131150pub struct Range < ' a , K : Hash + Ord , V > {
132- inner_range : btree_set :: Range < ' a , K > ,
151+ inner_range : Iter < ' a , K > ,
133152 map : & ' a HashMap < K , V > ,
134153}
135154impl < ' a , K : Hash + Ord , V : ' a > Iterator for Range < ' a , K , V > {
@@ -148,7 +167,7 @@ pub struct VacantEntry<'a, K: Hash + Ord, V> {
148167 #[ cfg( not( feature = "hashbrown" ) ) ]
149168 underlying_entry : hash_map:: VacantEntry < ' a , K , V > ,
150169 key : K ,
151- keys : & ' a mut BTreeSet < K > ,
170+ keys : & ' a mut Vec < K > ,
152171}
153172
154173/// An [`Entry`] for an existing key-value pair
@@ -157,7 +176,7 @@ pub struct OccupiedEntry<'a, K: Hash + Ord, V> {
157176 underlying_entry : hash_map:: OccupiedEntry < ' a , K , V , hash_map:: DefaultHashBuilder > ,
158177 #[ cfg( not( feature = "hashbrown" ) ) ]
159178 underlying_entry : hash_map:: OccupiedEntry < ' a , K , V > ,
160- keys : & ' a mut BTreeSet < K > ,
179+ keys : & ' a mut Vec < K > ,
161180}
162181
163182/// A mutable reference to a position in the map. This can be used to reference, add, or update the
@@ -172,7 +191,7 @@ pub enum Entry<'a, K: Hash + Ord, V> {
172191impl < ' a , K : Hash + Ord , V > VacantEntry < ' a , K , V > {
173192 /// Insert a value into the position described by this entry.
174193 pub fn insert ( self , value : V ) -> & ' a mut V {
175- assert ! ( self . keys. insert ( self . key) , "map and keys must be consistent" ) ;
194+ self . keys . push ( self . key ) ;
176195 self . underlying_entry . insert ( value)
177196 }
178197}
@@ -181,7 +200,8 @@ impl<'a, K: Hash + Ord, V> OccupiedEntry<'a, K, V> {
181200 /// Remove the value at the position described by this entry.
182201 pub fn remove_entry ( self ) -> ( K , V ) {
183202 let res = self . underlying_entry . remove_entry ( ) ;
184- assert ! ( self . keys. remove( & res. 0 ) , "map and keys must be consistent" ) ;
203+ let idx = self . keys . iter ( ) . position ( |k| k == & res. 0 ) . expect ( "map and keys must be consistent" ) ;
204+ self . keys . remove ( idx) ;
185205 res
186206 }
187207
0 commit comments