@@ -117,6 +117,24 @@ impl<K: Hash + Eq, V> LinkedHashMap<K, V> {
117
117
}
118
118
119
119
impl < K , V , S > LinkedHashMap < K , V , S > {
120
+ #[ inline]
121
+ fn detach ( & mut self , node : * mut LinkedHashMapEntry < K , V > ) {
122
+ unsafe {
123
+ ( * ( * node) . prev ) . next = ( * node) . next ;
124
+ ( * ( * node) . next ) . prev = ( * node) . prev ;
125
+ }
126
+ }
127
+
128
+ #[ inline]
129
+ fn attach ( & mut self , node : * mut LinkedHashMapEntry < K , V > ) {
130
+ unsafe {
131
+ ( * node) . next = ( * self . head ) . next ;
132
+ ( * node) . prev = self . head ;
133
+ ( * self . head ) . next = node;
134
+ ( * ( * node) . next ) . prev = node;
135
+ }
136
+ }
137
+
120
138
fn clear_free_list ( & mut self ) {
121
139
unsafe {
122
140
let mut free = self . free ;
@@ -128,6 +146,17 @@ impl<K, V, S> LinkedHashMap<K, V, S> {
128
146
self . free = ptr:: null_mut ( ) ;
129
147
}
130
148
}
149
+
150
+ fn ensure_guard_node ( & mut self ) {
151
+ if self . head . is_null ( ) {
152
+ // allocate the guard node if not present
153
+ unsafe {
154
+ self . head = Box :: into_raw ( Box :: new ( mem:: uninitialized ( ) ) ) ;
155
+ ( * self . head ) . next = self . head ;
156
+ ( * self . head ) . prev = self . head ;
157
+ }
158
+ }
159
+ }
131
160
}
132
161
133
162
impl < K : Hash + Eq , V , S : BuildHasher > LinkedHashMap < K , V , S > {
@@ -165,6 +194,42 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
165
194
self . clear_free_list ( ) ;
166
195
}
167
196
197
+ /// Gets the given key's corresponding entry in the map for in-place manipulation.
198
+ ///
199
+ /// # Examples
200
+ ///
201
+ /// ```
202
+ /// use linked_hash_map::LinkedHashMap;
203
+ ///
204
+ /// let mut letters = LinkedHashMap::new();
205
+ ///
206
+ /// for ch in "a short treatise on fungi".chars() {
207
+ /// let counter = letters.entry(ch).or_insert(0);
208
+ /// *counter += 1;
209
+ /// }
210
+ ///
211
+ /// assert_eq!(letters[&'s'], 2);
212
+ /// assert_eq!(letters[&'t'], 3);
213
+ /// assert_eq!(letters[&'u'], 1);
214
+ /// assert_eq!(letters.get(&'y'), None);
215
+ /// ```
216
+ pub fn entry ( & mut self , k : K ) -> Entry < K , V , S > {
217
+ let self_ptr: * mut Self = self ;
218
+
219
+ if let Some ( entry) = self . map . get_mut ( & KeyRef { k : & k} ) {
220
+ return Entry :: Occupied ( OccupiedEntry {
221
+ entry : & mut * * entry,
222
+ map : self_ptr,
223
+ marker : marker:: PhantomData ,
224
+ } ) ;
225
+ }
226
+
227
+ Entry :: Vacant ( VacantEntry {
228
+ key : k,
229
+ map : self ,
230
+ } )
231
+ }
232
+
168
233
/// Inserts a key-value pair into the map. If the key already existed, the old value is
169
234
/// returned.
170
235
///
@@ -180,14 +245,8 @@ impl<K: Hash + Eq, V, S: BuildHasher> LinkedHashMap<K, V, S> {
180
245
/// assert_eq!(map[&2], "b");
181
246
/// ```
182
247
pub fn insert ( & mut self , k : K , v : V ) -> Option < V > {
183
- if self . head . is_null ( ) {
184
- // allocate the guard node if not present
185
- unsafe {
186
- self . head = Box :: into_raw ( Box :: new ( mem:: uninitialized ( ) ) ) ;
187
- ( * self . head ) . next = self . head ;
188
- ( * self . head ) . prev = self . head ;
189
- }
190
- }
248
+ self . ensure_guard_node ( ) ;
249
+
191
250
let ( node_ptr, node_opt, old_val) = match self . map . get_mut ( & KeyRef { k : & k} ) {
192
251
Some ( node) => {
193
252
let old_val = mem:: replace ( & mut node. value , v) ;
@@ -592,27 +651,10 @@ impl<'a, K, V, S, Q: ?Sized> IndexMut<&'a Q> for LinkedHashMap<K, V, S>
592
651
}
593
652
}
594
653
595
- impl < K : Hash + Eq , V , S : BuildHasher > LinkedHashMap < K , V , S > {
596
- #[ inline]
597
- fn detach ( & mut self , node : * mut LinkedHashMapEntry < K , V > ) {
598
- unsafe {
599
- ( * ( * node) . prev ) . next = ( * node) . next ;
600
- ( * ( * node) . next ) . prev = ( * node) . prev ;
601
- }
602
- }
603
-
604
- #[ inline]
605
- fn attach ( & mut self , node : * mut LinkedHashMapEntry < K , V > ) {
606
- unsafe {
607
- ( * node) . next = ( * self . head ) . next ;
608
- ( * node) . prev = self . head ;
609
- ( * self . head ) . next = node;
610
- ( * ( * node) . next ) . prev = node;
611
- }
612
- }
613
- }
614
-
615
654
#[ cfg( not( feature = "nightly" ) ) ]
655
+ // FIXME: `HashMap` doesn't expose its hash state, so we cannot clone fully parameterized
656
+ // `LinkedHashMap`s without cloning the original map and clearing it. For now, only
657
+ // `LinkedHashMap<K, V>`s implement `Clone`.
616
658
impl < K : Hash + Eq + Clone , V : Clone > Clone for LinkedHashMap < K , V > {
617
659
fn clone ( & self ) -> Self {
618
660
self . iter ( ) . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) ) . collect ( )
@@ -895,6 +937,163 @@ impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a mut LinkedHashMap
895
937
fn into_iter ( self ) -> IterMut < ' a , K , V > { self . iter_mut ( ) }
896
938
}
897
939
940
+ /// A view into a single location in a map, which may be vacant or occupied.
941
+ pub enum Entry < ' a , K : ' a , V : ' a , S : ' a + HashState > {
942
+ /// An occupied Entry.
943
+ Occupied ( OccupiedEntry < ' a , K , V , S > ) ,
944
+ /// A vacant Entry.
945
+ Vacant ( VacantEntry < ' a , K , V , S > ) ,
946
+ }
947
+
948
+ /// A view into a single occupied location in a LinkedHashMap.
949
+ pub struct OccupiedEntry < ' a , K : ' a , V : ' a , S : ' a + HashState > {
950
+ entry : * mut LinkedHashMapEntry < K , V > ,
951
+ map : * mut LinkedHashMap < K , V , S > ,
952
+ marker : marker:: PhantomData < & ' a K > ,
953
+ }
954
+
955
+ /// A view into a single empty location in a HashMap.
956
+ pub struct VacantEntry < ' a , K : ' a , V : ' a , S : ' a + HashState > {
957
+ key : K ,
958
+ map : & ' a mut LinkedHashMap < K , V , S > ,
959
+ }
960
+
961
+ impl < ' a , K : Hash + Eq , V , S : HashState > Entry < ' a , K , V , S > {
962
+ /// Returns the entry key
963
+ ///
964
+ /// # Examples
965
+ ///
966
+ /// ```
967
+ /// use linked_hash_map::LinkedHashMap;
968
+ ///
969
+ /// let mut map = LinkedHashMap::<String, u32>::new();
970
+ ///
971
+ /// assert_eq!("hello", map.entry("hello".to_string()).key());
972
+ /// ```
973
+ pub fn key ( & self ) -> & K {
974
+ match * self {
975
+ Entry :: Occupied ( ref e) => e. key ( ) ,
976
+ Entry :: Vacant ( ref e) => e. key ( ) ,
977
+ }
978
+ }
979
+
980
+ /// Ensures a value is in the entry by inserting the default if empty, and returns
981
+ /// a mutable reference to the value in the entry.
982
+ pub fn or_insert ( self , default : V ) -> & ' a mut V {
983
+ match self {
984
+ Entry :: Occupied ( entry) => entry. into_mut ( ) ,
985
+ Entry :: Vacant ( entry) => entry. insert ( default) ,
986
+ }
987
+ }
988
+
989
+ /// Ensures a value is in the entry by inserting the result of the default function if empty,
990
+ /// and returns a mutable reference to the value in the entry.
991
+ pub fn or_insert_with < F : FnOnce ( ) -> V > ( self , default : F ) -> & ' a mut V {
992
+ match self {
993
+ Entry :: Occupied ( entry) => entry. into_mut ( ) ,
994
+ Entry :: Vacant ( entry) => entry. insert ( default ( ) ) ,
995
+ }
996
+ }
997
+ }
998
+
999
+ impl < ' a , K : Hash + Eq , V , S : HashState > OccupiedEntry < ' a , K , V , S > {
1000
+ /// Gets a reference to the entry key
1001
+ ///
1002
+ /// # Examples
1003
+ ///
1004
+ /// ```
1005
+ /// use linked_hash_map::LinkedHashMap;
1006
+ ///
1007
+ /// let mut map = LinkedHashMap::new();
1008
+ ///
1009
+ /// map.insert("foo".to_string(), 1);
1010
+ /// assert_eq!("foo", map.entry("foo".to_string()).key());
1011
+ /// ```
1012
+ pub fn key ( & self ) -> & K {
1013
+ unsafe { & ( * self . entry ) . key }
1014
+ }
1015
+
1016
+ /// Gets a reference to the value in the entry.
1017
+ pub fn get ( & self ) -> & V {
1018
+ unsafe { & ( * self . entry ) . value }
1019
+ }
1020
+
1021
+ /// Gets a mutable reference to the value in the entry.
1022
+ pub fn get_mut ( & mut self ) -> & mut V {
1023
+ unsafe { & mut ( * self . entry ) . value }
1024
+ }
1025
+
1026
+ /// Converts the OccupiedEntry into a mutable reference to the value in the entry
1027
+ /// with a lifetime bound to the map itself
1028
+ pub fn into_mut ( self ) -> & ' a mut V {
1029
+ unsafe { & mut ( * self . entry ) . value }
1030
+ }
1031
+
1032
+ /// Sets the value of the entry, and returns the entry's old value
1033
+ pub fn insert ( & mut self , value : V ) -> V {
1034
+ unsafe {
1035
+ ( * self . map ) . ensure_guard_node ( ) ;
1036
+
1037
+ let old_val = mem:: replace ( & mut ( * self . entry ) . value , value) ;
1038
+ let node_ptr: * mut LinkedHashMapEntry < K , V > = self . entry ;
1039
+
1040
+ // Existing node, just update LRU position
1041
+ ( * self . map ) . detach ( node_ptr) ;
1042
+ ( * self . map ) . attach ( node_ptr) ;
1043
+
1044
+ old_val
1045
+ }
1046
+ }
1047
+
1048
+ /// Takes the value out of the entry, and returns it
1049
+ pub fn remove ( self ) -> V {
1050
+ unsafe { ( * self . map ) . remove ( & ( * self . entry ) . key ) } . unwrap ( )
1051
+ }
1052
+ }
1053
+
1054
+ impl < ' a , K : ' a + Hash + Eq , V : ' a , S : HashState > VacantEntry < ' a , K , V , S > {
1055
+ /// Gets a reference to the entry key
1056
+ ///
1057
+ /// # Examples
1058
+ ///
1059
+ /// ```
1060
+ /// use linked_hash_map::LinkedHashMap;
1061
+ ///
1062
+ /// let mut map = LinkedHashMap::<String, u32>::new();
1063
+ ///
1064
+ /// assert_eq!("foo", map.entry("foo".to_string()).key());
1065
+ /// ```
1066
+ pub fn key ( & self ) -> & K {
1067
+ & self . key
1068
+ }
1069
+
1070
+ /// Sets the value of the entry with the VacantEntry's key,
1071
+ /// and returns a mutable reference to it
1072
+ pub fn insert ( self , value : V ) -> & ' a mut V {
1073
+ self . map . ensure_guard_node ( ) ;
1074
+
1075
+ let mut node = if self . map . free . is_null ( ) {
1076
+ Box :: new ( LinkedHashMapEntry :: new ( self . key , value) )
1077
+ } else {
1078
+ // use a recycled box
1079
+ unsafe {
1080
+ let free = self . map . free ;
1081
+ self . map . free = ( * free) . next ;
1082
+ ptr:: write ( free, LinkedHashMapEntry :: new ( self . key , value) ) ;
1083
+ Box :: from_raw ( free)
1084
+ }
1085
+ } ;
1086
+
1087
+ let node_ptr: * mut LinkedHashMapEntry < K , V > = & mut * node;
1088
+ let keyref = unsafe { & ( * node_ptr) . key } ;
1089
+
1090
+ self . map . attach ( node_ptr) ;
1091
+
1092
+ & mut self . map . map . entry ( KeyRef { k : keyref} )
1093
+ . or_insert ( node) . value
1094
+ }
1095
+ }
1096
+
898
1097
#[ cfg( all( feature = "nightly" , test) ) ]
899
1098
mod bench {
900
1099
extern crate test;
0 commit comments