@@ -124,6 +124,24 @@ impl<K: Hash + Eq, V> LinkedHashMap<K, V> {
124
124
}
125
125
126
126
impl < K , V , S > LinkedHashMap < K , V , S > {
127
+ #[ inline]
128
+ fn detach ( & mut self , node : * mut Node < K , V > ) {
129
+ unsafe {
130
+ ( * ( * node) . prev ) . next = ( * node) . next ;
131
+ ( * ( * node) . next ) . prev = ( * node) . prev ;
132
+ }
133
+ }
134
+
135
+ #[ inline]
136
+ fn attach ( & mut self , node : * mut Node < K , V > ) {
137
+ unsafe {
138
+ ( * node) . next = ( * self . head ) . next ;
139
+ ( * node) . prev = self . head ;
140
+ ( * self . head ) . next = node;
141
+ ( * ( * node) . next ) . prev = node;
142
+ }
143
+ }
144
+
127
145
// Caller must check `!self.head.is_null()`
128
146
unsafe fn drop_entries ( & mut self ) {
129
147
let mut cur = ( * self . head ) . next ;
@@ -145,6 +163,17 @@ impl<K, V, S> LinkedHashMap<K, V, S> {
145
163
self . free = ptr:: null_mut ( ) ;
146
164
}
147
165
}
166
+
167
+ fn ensure_guard_node ( & mut self ) {
168
+ if self . head . is_null ( ) {
169
+ // allocate the guard node if not present
170
+ unsafe {
171
+ self . head = Box :: into_raw ( Box :: new ( mem:: uninitialized ( ) ) ) ;
172
+ ( * self . head ) . next = self . head ;
173
+ ( * self . head ) . prev = self . head ;
174
+ }
175
+ }
176
+ }
148
177
}
149
178
150
179
impl < K : Hash + Eq , V , S : BuildHasher > LinkedHashMap < K , V , S > {
@@ -182,6 +211,79 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
182
211
self . clear_free_list ( ) ;
183
212
}
184
213
214
+ /// Gets the given key's corresponding entry in the map for in-place manipulation.
215
+ ///
216
+ /// # Examples
217
+ ///
218
+ /// ```
219
+ /// use linked_hash_map::LinkedHashMap;
220
+ ///
221
+ /// let mut letters = LinkedHashMap::new();
222
+ ///
223
+ /// for ch in "a short treatise on fungi".chars() {
224
+ /// let counter = letters.entry(ch).or_insert(0);
225
+ /// *counter += 1;
226
+ /// }
227
+ ///
228
+ /// assert_eq!(letters[&'s'], 2);
229
+ /// assert_eq!(letters[&'t'], 3);
230
+ /// assert_eq!(letters[&'u'], 1);
231
+ /// assert_eq!(letters.get(&'y'), None);
232
+ /// ```
233
+ pub fn entry ( & mut self , k : K ) -> Entry < K , V , S > {
234
+ let self_ptr: * mut Self = self ;
235
+
236
+ if let Some ( entry) = self . map . get_mut ( & KeyRef { k : & k} ) {
237
+ return Entry :: Occupied ( OccupiedEntry {
238
+ entry : * entry,
239
+ map : self_ptr,
240
+ marker : marker:: PhantomData ,
241
+ } ) ;
242
+ }
243
+
244
+ Entry :: Vacant ( VacantEntry {
245
+ key : k,
246
+ map : self ,
247
+ } )
248
+ }
249
+
250
+ /// Returns an iterator visiting all entries in insertion order.
251
+ /// Iterator element type is `OccupiedEntry<K, V, S>`. Allows for removal
252
+ /// as well as replacing the entry.
253
+ ///
254
+ /// # Examples
255
+ /// ```
256
+ /// use linked_hash_map::LinkedHashMap;
257
+ ///
258
+ /// let mut map = LinkedHashMap::new();
259
+ /// map.insert("a", 10);
260
+ /// map.insert("c", 30);
261
+ /// map.insert("b", 20);
262
+ ///
263
+ /// {
264
+ /// let mut iter = map.entries();
265
+ /// let mut entry = iter.next().unwrap();
266
+ /// assert_eq!(&"a", entry.key());
267
+ /// *entry.get_mut() = 17;
268
+ /// }
269
+ ///
270
+ /// assert_eq!(&17, map.get(&"a").unwrap());
271
+ /// ```
272
+ pub fn entries ( & mut self ) -> Entries < K , V , S > {
273
+ let head = if ! self . head . is_null ( ) {
274
+ unsafe { ( * self . head ) . prev }
275
+ } else {
276
+ ptr:: null_mut ( )
277
+ } ;
278
+ Entries {
279
+ map : self ,
280
+ head : head,
281
+ tail : self . head ,
282
+ remaining : self . len ( ) ,
283
+ marker : marker:: PhantomData ,
284
+ }
285
+ }
286
+
185
287
/// Inserts a key-value pair into the map. If the key already existed, the old value is
186
288
/// returned.
187
289
///
@@ -197,14 +299,8 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
197
299
/// assert_eq!(map[&2], "b");
198
300
/// ```
199
301
pub fn insert ( & mut self , k : K , v : V ) -> Option < V > {
200
- if self . head . is_null ( ) {
201
- // allocate the guard node if not present
202
- unsafe {
203
- self . head = Box :: into_raw ( Box :: new ( mem:: uninitialized ( ) ) ) ;
204
- ( * self . head ) . next = self . head ;
205
- ( * self . head ) . prev = self . head ;
206
- }
207
- }
302
+ self . ensure_guard_node ( ) ;
303
+
208
304
let ( node, old_val) = match self . map . get ( & KeyRef { k : & k} ) {
209
305
Some ( node) => {
210
306
let old_val = unsafe { ptr:: replace ( & mut ( * * node) . value , v) } ;
@@ -612,26 +708,6 @@ impl<'a, K, V, S, Q: ?Sized> IndexMut<&'a Q> for LinkedHashMap<K, V, S>
612
708
}
613
709
}
614
710
615
- impl < K : Hash + Eq , V , S : BuildHasher > LinkedHashMap < K , V , S > {
616
- #[ inline]
617
- fn detach ( & mut self , node : * mut Node < K , V > ) {
618
- unsafe {
619
- ( * ( * node) . prev ) . next = ( * node) . next ;
620
- ( * ( * node) . next ) . prev = ( * node) . prev ;
621
- }
622
- }
623
-
624
- #[ inline]
625
- fn attach ( & mut self , node : * mut Node < K , V > ) {
626
- unsafe {
627
- ( * node) . next = ( * self . head ) . next ;
628
- ( * node) . prev = self . head ;
629
- ( * self . head ) . next = node;
630
- ( * ( * node) . next ) . prev = node;
631
- }
632
- }
633
- }
634
-
635
711
impl < K : Hash + Eq + Clone , V : Clone , S : BuildHasher + Clone > Clone for LinkedHashMap < K , V , S > {
636
712
fn clone ( & self ) -> Self {
637
713
let mut map = Self :: with_hasher ( self . map . hasher ( ) . clone ( ) ) ;
@@ -760,18 +836,32 @@ pub struct IntoIter<K, V> {
760
836
marker : marker:: PhantomData < ( K , V ) > ,
761
837
}
762
838
839
+ /// An insertion-order iterator over a `LinkedHashMap`'s entries represented as
840
+ /// an `OccupiedEntry`.
841
+ pub struct Entries < ' a , K : ' a , V : ' a , S : ' a = hash_map:: RandomState > {
842
+ map : * mut LinkedHashMap < K , V , S > ,
843
+ head : * mut Node < K , V > ,
844
+ tail : * mut Node < K , V > ,
845
+ remaining : usize ,
846
+ marker : marker:: PhantomData < ( & ' a K , & ' a mut V , & ' a S ) > ,
847
+ }
848
+
763
849
unsafe impl < ' a , K , V > Send for Iter < ' a , K , V > where K : Send , V : Send { }
764
850
765
851
unsafe impl < ' a , K , V > Send for IterMut < ' a , K , V > where K : Send , V : Send { }
766
852
767
853
unsafe impl < K , V > Send for IntoIter < K , V > where K : Send , V : Send { }
768
854
855
+ unsafe impl < ' a , K , V , S > Send for Entries < ' a , K , V , S > where K : Send , V : Send , S : Send { }
856
+
769
857
unsafe impl < ' a , K , V > Sync for Iter < ' a , K , V > where K : Sync , V : Sync { }
770
858
771
859
unsafe impl < ' a , K , V > Sync for IterMut < ' a , K , V > where K : Sync , V : Sync { }
772
860
773
861
unsafe impl < K , V > Sync for IntoIter < K , V > where K : Sync , V : Sync { }
774
862
863
+ unsafe impl < ' a , K , V , S > Sync for Entries < ' a , K , V , S > where K : Sync , V : Sync , S : Sync { }
864
+
775
865
impl < ' a , K , V > Clone for Iter < ' a , K , V > {
776
866
fn clone ( & self ) -> Self { Iter { ..* self } }
777
867
}
@@ -874,6 +964,32 @@ impl<K, V> Iterator for IntoIter<K, V> {
874
964
}
875
965
}
876
966
967
+ impl < ' a , K , V , S : BuildHasher > Iterator for Entries < ' a , K , V , S > {
968
+ type Item = OccupiedEntry < ' a , K , V , S > ;
969
+
970
+ fn next ( & mut self ) -> Option < OccupiedEntry < ' a , K , V , S > > {
971
+ if self . head == self . tail {
972
+ None
973
+ } else {
974
+ self . remaining -= 1 ;
975
+ unsafe {
976
+ let r = Some ( OccupiedEntry {
977
+ map : self . map ,
978
+ entry : self . head ,
979
+ marker : marker:: PhantomData ,
980
+ } ) ;
981
+
982
+ self . head = ( * self . head ) . prev ;
983
+ r
984
+ }
985
+ }
986
+ }
987
+
988
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
989
+ ( self . remaining , Some ( self . remaining ) )
990
+ }
991
+ }
992
+
877
993
impl < ' a , K , V > DoubleEndedIterator for Iter < ' a , K , V > {
878
994
fn next_back ( & mut self ) -> Option < ( & ' a K , & ' a V ) > {
879
995
if self . head == self . tail {
@@ -1029,6 +1145,162 @@ impl<K: Hash + Eq, V, S: BuildHasher> IntoIterator for LinkedHashMap<K, V, S> {
1029
1145
}
1030
1146
}
1031
1147
1148
+ /// A view into a single location in a map, which may be vacant or occupied.
1149
+ pub enum Entry < ' a , K : ' a , V : ' a , S : ' a = hash_map:: RandomState > {
1150
+ /// An occupied Entry.
1151
+ Occupied ( OccupiedEntry < ' a , K , V , S > ) ,
1152
+ /// A vacant Entry.
1153
+ Vacant ( VacantEntry < ' a , K , V , S > ) ,
1154
+ }
1155
+
1156
+ /// A view into a single occupied location in a `LinkedHashMap`.
1157
+ pub struct OccupiedEntry < ' a , K : ' a , V : ' a , S : ' a = hash_map:: RandomState > {
1158
+ entry : * mut Node < K , V > ,
1159
+ map : * mut LinkedHashMap < K , V , S > ,
1160
+ marker : marker:: PhantomData < & ' a K > ,
1161
+ }
1162
+
1163
+ /// A view into a single empty location in a `LinkedHashMap`.
1164
+ pub struct VacantEntry < ' a , K : ' a , V : ' a , S : ' a = hash_map:: RandomState > {
1165
+ key : K ,
1166
+ map : & ' a mut LinkedHashMap < K , V , S > ,
1167
+ }
1168
+
1169
+ impl < ' a , K : Hash + Eq , V , S : BuildHasher > Entry < ' a , K , V , S > {
1170
+ /// Returns the entry key
1171
+ ///
1172
+ /// # Examples
1173
+ ///
1174
+ /// ```
1175
+ /// use linked_hash_map::LinkedHashMap;
1176
+ ///
1177
+ /// let mut map = LinkedHashMap::<String, u32>::new();
1178
+ ///
1179
+ /// assert_eq!("hello", map.entry("hello".to_string()).key());
1180
+ /// ```
1181
+ pub fn key ( & self ) -> & K {
1182
+ match * self {
1183
+ Entry :: Occupied ( ref e) => e. key ( ) ,
1184
+ Entry :: Vacant ( ref e) => e. key ( ) ,
1185
+ }
1186
+ }
1187
+
1188
+ /// Ensures a value is in the entry by inserting the default if empty, and returns
1189
+ /// a mutable reference to the value in the entry.
1190
+ pub fn or_insert ( self , default : V ) -> & ' a mut V {
1191
+ match self {
1192
+ Entry :: Occupied ( entry) => entry. into_mut ( ) ,
1193
+ Entry :: Vacant ( entry) => entry. insert ( default) ,
1194
+ }
1195
+ }
1196
+
1197
+ /// Ensures a value is in the entry by inserting the result of the default function if empty,
1198
+ /// and returns a mutable reference to the value in the entry.
1199
+ pub fn or_insert_with < F : FnOnce ( ) -> V > ( self , default : F ) -> & ' a mut V {
1200
+ match self {
1201
+ Entry :: Occupied ( entry) => entry. into_mut ( ) ,
1202
+ Entry :: Vacant ( entry) => entry. insert ( default ( ) ) ,
1203
+ }
1204
+ }
1205
+ }
1206
+
1207
+ impl < ' a , K : Hash + Eq , V , S : BuildHasher > OccupiedEntry < ' a , K , V , S > {
1208
+ /// Gets a reference to the entry key
1209
+ ///
1210
+ /// # Examples
1211
+ ///
1212
+ /// ```
1213
+ /// use linked_hash_map::LinkedHashMap;
1214
+ ///
1215
+ /// let mut map = LinkedHashMap::new();
1216
+ ///
1217
+ /// map.insert("foo".to_string(), 1);
1218
+ /// assert_eq!("foo", map.entry("foo".to_string()).key());
1219
+ /// ```
1220
+ pub fn key ( & self ) -> & K {
1221
+ unsafe { & ( * self . entry ) . key }
1222
+ }
1223
+
1224
+ /// Gets a reference to the value in the entry.
1225
+ pub fn get ( & self ) -> & V {
1226
+ unsafe { & ( * self . entry ) . value }
1227
+ }
1228
+
1229
+ /// Gets a mutable reference to the value in the entry.
1230
+ pub fn get_mut ( & mut self ) -> & mut V {
1231
+ unsafe { & mut ( * self . entry ) . value }
1232
+ }
1233
+
1234
+ /// Converts the OccupiedEntry into a mutable reference to the value in the entry
1235
+ /// with a lifetime bound to the map itself
1236
+ pub fn into_mut ( self ) -> & ' a mut V {
1237
+ unsafe { & mut ( * self . entry ) . value }
1238
+ }
1239
+
1240
+ /// Sets the value of the entry, and returns the entry's old value
1241
+ pub fn insert ( & mut self , value : V ) -> V {
1242
+ unsafe {
1243
+ ( * self . map ) . ensure_guard_node ( ) ;
1244
+
1245
+ let old_val = mem:: replace ( & mut ( * self . entry ) . value , value) ;
1246
+ let node_ptr: * mut Node < K , V > = self . entry ;
1247
+
1248
+ // Existing node, just update LRU position
1249
+ ( * self . map ) . detach ( node_ptr) ;
1250
+ ( * self . map ) . attach ( node_ptr) ;
1251
+
1252
+ old_val
1253
+ }
1254
+ }
1255
+
1256
+ /// Takes the value out of the entry, and returns it
1257
+ pub fn remove ( self ) -> V {
1258
+ unsafe { ( * self . map ) . remove ( & ( * self . entry ) . key ) } . unwrap ( )
1259
+ }
1260
+ }
1261
+
1262
+ impl < ' a , K : ' a + Hash + Eq , V : ' a , S : BuildHasher > VacantEntry < ' a , K , V , S > {
1263
+ /// Gets a reference to the entry key
1264
+ ///
1265
+ /// # Examples
1266
+ ///
1267
+ /// ```
1268
+ /// use linked_hash_map::LinkedHashMap;
1269
+ ///
1270
+ /// let mut map = LinkedHashMap::<String, u32>::new();
1271
+ ///
1272
+ /// assert_eq!("foo", map.entry("foo".to_string()).key());
1273
+ /// ```
1274
+ pub fn key ( & self ) -> & K {
1275
+ & self . key
1276
+ }
1277
+
1278
+ /// Sets the value of the entry with the VacantEntry's key,
1279
+ /// and returns a mutable reference to it
1280
+ pub fn insert ( self , value : V ) -> & ' a mut V {
1281
+ self . map . ensure_guard_node ( ) ;
1282
+
1283
+ let node = if self . map . free . is_null ( ) {
1284
+ Box :: into_raw ( Box :: new ( Node :: new ( self . key , value) ) )
1285
+ } else {
1286
+ // use a recycled box
1287
+ unsafe {
1288
+ let free = self . map . free ;
1289
+ self . map . free = ( * free) . next ;
1290
+ ptr:: write ( free, Node :: new ( self . key , value) ) ;
1291
+ free
1292
+ }
1293
+ } ;
1294
+
1295
+ let keyref = unsafe { & ( * node) . key } ;
1296
+
1297
+ self . map . attach ( node) ;
1298
+
1299
+ let ret = self . map . map . entry ( KeyRef { k : keyref} ) . or_insert ( node) ;
1300
+ unsafe { & mut ( * * ret) . value }
1301
+ }
1302
+ }
1303
+
1032
1304
#[ cfg( all( feature = "nightly" , test) ) ]
1033
1305
mod bench {
1034
1306
extern crate test;
0 commit comments