@@ -20,7 +20,7 @@ use fmt::{self, Debug};
20
20
use hash:: { Hash , Hasher , BuildHasher , SipHasher13 } ;
21
21
use iter:: { FromIterator , FusedIterator } ;
22
22
use mem:: { self , replace} ;
23
- use ops:: { Deref , Index } ;
23
+ use ops:: { Deref , DerefMut , Index } ;
24
24
use sys;
25
25
26
26
use super :: table:: { self , Bucket , EmptyBucket , Fallibility , FullBucket , FullBucketMut , RawTable ,
@@ -435,12 +435,13 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, is_match: F) -> InternalE
435
435
return InternalEntry :: TableIsEmpty ;
436
436
}
437
437
438
- search_hashed_nonempty ( table, hash, is_match)
438
+ search_hashed_nonempty ( table, hash, is_match, true )
439
439
}
440
440
441
441
/// Search for a pre-hashed key when the hash map is known to be non-empty.
442
442
#[ inline]
443
- fn search_hashed_nonempty < K , V , M , F > ( table : M , hash : SafeHash , mut is_match : F )
443
+ fn search_hashed_nonempty < K , V , M , F > ( table : M , hash : SafeHash , mut is_match : F ,
444
+ compare_hashes : bool )
444
445
-> InternalEntry < K , V , M >
445
446
where M : Deref < Target = RawTable < K , V > > ,
446
447
F : FnMut ( & K ) -> bool
@@ -476,7 +477,7 @@ fn search_hashed_nonempty<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F)
476
477
}
477
478
478
479
// If the hash doesn't match, it can't be this one..
479
- if hash == full. hash ( ) {
480
+ if !compare_hashes || hash == full. hash ( ) {
480
481
// If the key doesn't match, it can't be this one..
481
482
if is_match ( full. read ( ) . 0 ) {
482
483
return InternalEntry :: Occupied { elem : full } ;
@@ -488,6 +489,57 @@ fn search_hashed_nonempty<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F)
488
489
}
489
490
}
490
491
492
+ /// Same as `search_hashed_nonempty` but for mutable access.
493
+ #[ inline]
494
+ fn search_hashed_nonempty_mut < K , V , M , F > ( table : M , hash : SafeHash , mut is_match : F ,
495
+ compare_hashes : bool )
496
+ -> InternalEntry < K , V , M >
497
+ where M : DerefMut < Target = RawTable < K , V > > ,
498
+ F : FnMut ( & K ) -> bool
499
+ {
500
+ // Do not check the capacity as an extra branch could slow the lookup.
501
+
502
+ let size = table. size ( ) ;
503
+ let mut probe = Bucket :: new ( table, hash) ;
504
+ let mut displacement = 0 ;
505
+
506
+ loop {
507
+ let mut full = match probe. peek ( ) {
508
+ Empty ( bucket) => {
509
+ // Found a hole!
510
+ return InternalEntry :: Vacant {
511
+ hash,
512
+ elem : NoElem ( bucket, displacement) ,
513
+ } ;
514
+ }
515
+ Full ( bucket) => bucket,
516
+ } ;
517
+
518
+ let probe_displacement = full. displacement ( ) ;
519
+
520
+ if probe_displacement < displacement {
521
+ // Found a luckier bucket than me.
522
+ // We can finish the search early if we hit any bucket
523
+ // with a lower distance to initial bucket than we've probed.
524
+ return InternalEntry :: Vacant {
525
+ hash,
526
+ elem : NeqElem ( full, probe_displacement) ,
527
+ } ;
528
+ }
529
+
530
+ // If the hash doesn't match, it can't be this one..
531
+ if hash == full. hash ( ) || !compare_hashes {
532
+ // If the key doesn't match, it can't be this one..
533
+ if is_match ( full. read_mut ( ) . 0 ) {
534
+ return InternalEntry :: Occupied { elem : full } ;
535
+ }
536
+ }
537
+ displacement += 1 ;
538
+ probe = full. next ( ) ;
539
+ debug_assert ! ( displacement <= size) ;
540
+ }
541
+ }
542
+
491
543
fn pop_internal < K , V > ( starting_bucket : FullBucketMut < K , V > )
492
544
-> ( K , V , & mut RawTable < K , V > )
493
545
{
@@ -593,7 +645,7 @@ impl<K, V, S> HashMap<K, V, S>
593
645
}
594
646
595
647
let hash = self . make_hash ( q) ;
596
- search_hashed_nonempty ( & self . table , hash, |k| q. eq ( k. borrow ( ) ) )
648
+ search_hashed_nonempty ( & self . table , hash, |k| q. eq ( k. borrow ( ) ) , true )
597
649
. into_occupied_bucket ( )
598
650
}
599
651
@@ -608,7 +660,7 @@ impl<K, V, S> HashMap<K, V, S>
608
660
}
609
661
610
662
let hash = self . make_hash ( q) ;
611
- search_hashed_nonempty ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) )
663
+ search_hashed_nonempty ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) , true )
612
664
. into_occupied_bucket ( )
613
665
}
614
666
@@ -1484,6 +1536,68 @@ impl<K, V, S> HashMap<K, V, S>
1484
1536
}
1485
1537
}
1486
1538
1539
+ impl < K , V , S > HashMap < K , V , S >
1540
+ where K : Eq + Hash ,
1541
+ S : BuildHasher
1542
+ {
1543
+ /// Creates a raw entry builder for the HashMap.
1544
+ ///
1545
+ /// Raw entries provide the lowest level of control for searching and
1546
+ /// manipulating a map. They must be manually initialized with a hash and
1547
+ /// then manually searched. After this, insertions into a vacant entry
1548
+ /// still require an owned key to be provided.
1549
+ ///
1550
+ /// Raw entries are useful for such exotic situations as:
1551
+ ///
1552
+ /// * Hash memoization
1553
+ /// * Deferring the creation of an owned key until it is known to be required
1554
+ /// * Using a search key that doesn't work with the Borrow trait
1555
+ /// * Using custom comparison logic without newtype wrappers
1556
+ ///
1557
+ /// Because raw entries provide much more low-level control, it's much easier
1558
+ /// to put the HashMap into an inconsistent state which, while memory-safe,
1559
+ /// will cause the map to produce seemingly random results. Higher-level and
1560
+ /// more foolproof APIs like `entry` should be preferred when possible.
1561
+ ///
1562
+ /// In particular, the hash used to initialized the raw entry must still be
1563
+ /// consistent with the hash of the key that is ultimately stored in the entry.
1564
+ /// This is because implementations of HashMap may need to recompute hashes
1565
+ /// when resizing, at which point only the keys are available.
1566
+ ///
1567
+ /// Raw entries give mutable access to the keys. This must not be used
1568
+ /// to modify how the key would compare or hash, as the map will not re-evaluate
1569
+ /// where the key should go, meaning the keys may become "lost" if their
1570
+ /// location does not reflect their state. For instance, if you change a key
1571
+ /// so that the map now contains keys which compare equal, search may start
1572
+ /// acting eratically, with two keys randomly masking eachother. Implementations
1573
+ /// are free to assume this doesn't happen (within the limits of memory-safety).
1574
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1575
+ pub fn raw_entry_mut ( & mut self ) -> RawEntryBuilderMut < K , V , S > {
1576
+ self . reserve ( 1 ) ;
1577
+ RawEntryBuilderMut { map : self }
1578
+ }
1579
+
1580
+ /// Creates a raw immutable entry builder for the HashMap.
1581
+ ///
1582
+ /// Raw entries provide the lowest level of control for searching and
1583
+ /// manipulating a map. They must be manually initialized with a hash and
1584
+ /// then manually searched.
1585
+ ///
1586
+ /// This is useful for
1587
+ /// * Hash memoization
1588
+ /// * Using a search key that doesn't work with the Borrow trait
1589
+ /// * Using custom comparison logic without newtype wrappers
1590
+ ///
1591
+ /// Unless you are in such a situation, higher-level and more foolproof APIs like
1592
+ /// `get` should be preferred.
1593
+ ///
1594
+ /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`.
1595
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1596
+ pub fn raw_entry ( & self ) -> RawEntryBuilder < K , V , S > {
1597
+ RawEntryBuilder { map : self }
1598
+ }
1599
+ }
1600
+
1487
1601
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1488
1602
impl < K , V , S > PartialEq for HashMap < K , V , S >
1489
1603
where K : Eq + Hash ,
@@ -1724,6 +1838,456 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
1724
1838
}
1725
1839
}
1726
1840
1841
+ /// A builder for computing where in a HashMap a key-value pair would be stored.
1842
+ ///
1843
+ /// See the [`HashMap::raw_entry_mut`] docs for usage examples.
1844
+ ///
1845
+ /// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut
1846
+
1847
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1848
+ pub struct RawEntryBuilderMut < ' a , K : ' a , V : ' a , S : ' a > {
1849
+ map : & ' a mut HashMap < K , V , S > ,
1850
+ }
1851
+
1852
+ /// A view into a single entry in a map, which may either be vacant or occupied.
1853
+ ///
1854
+ /// This is a lower-level version of [`Entry`].
1855
+ ///
1856
+ /// This `enum` is constructed from the [`raw_entry`] method on [`HashMap`].
1857
+ ///
1858
+ /// [`HashMap`]: struct.HashMap.html
1859
+ /// [`Entry`]: enum.Entry.html
1860
+ /// [`raw_entry`]: struct.HashMap.html#method.raw_entry
1861
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1862
+ pub enum RawEntryMut < ' a , K : ' a , V : ' a , S : ' a > {
1863
+ /// An occupied entry.
1864
+ Occupied ( RawOccupiedEntryMut < ' a , K , V > ) ,
1865
+ /// A vacant entry.
1866
+ Vacant ( RawVacantEntryMut < ' a , K , V , S > ) ,
1867
+ }
1868
+
1869
+ /// A view into an occupied entry in a `HashMap`.
1870
+ /// It is part of the [`RawEntryMut`] enum.
1871
+ ///
1872
+ /// [`RawEntryMut`]: enum.RawEntryMut.html
1873
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1874
+ pub struct RawOccupiedEntryMut < ' a , K : ' a , V : ' a > {
1875
+ elem : FullBucket < K , V , & ' a mut RawTable < K , V > > ,
1876
+ }
1877
+
1878
+ /// A view into a vacant entry in a `HashMap`.
1879
+ /// It is part of the [`RawEntryMut`] enum.
1880
+ ///
1881
+ /// [`RawEntryMut`]: enum.RawEntryMut.html
1882
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1883
+ pub struct RawVacantEntryMut < ' a , K : ' a , V : ' a , S : ' a > {
1884
+ elem : VacantEntryState < K , V , & ' a mut RawTable < K , V > > ,
1885
+ hash_builder : & ' a S ,
1886
+ }
1887
+
1888
+ /// A builder for computing where in a HashMap a key-value pair would be stored.
1889
+ ///
1890
+ /// See the [`HashMap::raw_entry`] docs for usage examples.
1891
+ ///
1892
+ /// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry
1893
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1894
+ pub struct RawEntryBuilder < ' a , K : ' a , V : ' a , S : ' a > {
1895
+ map : & ' a HashMap < K , V , S > ,
1896
+ }
1897
+
1898
+ impl < ' a , K , V , S > RawEntryBuilderMut < ' a , K , V , S >
1899
+ where S : BuildHasher ,
1900
+ K : Eq + Hash ,
1901
+ {
1902
+ /// Create a `RawEntryMut` from the given key.
1903
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1904
+ pub fn from_key < Q : ?Sized > ( self , k : & Q ) -> RawEntryMut < ' a , K , V , S >
1905
+ where K : Borrow < Q > ,
1906
+ Q : Hash + Eq
1907
+ {
1908
+ let mut hasher = self . map . hash_builder . build_hasher ( ) ;
1909
+ k. hash ( & mut hasher) ;
1910
+ self . from_key_hashed_nocheck ( hasher. finish ( ) , k)
1911
+ }
1912
+
1913
+ /// Create a `RawEntryMut` from the given key and its hash.
1914
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1915
+ pub fn from_key_hashed_nocheck < Q : ?Sized > ( self , hash : u64 , k : & Q ) -> RawEntryMut < ' a , K , V , S >
1916
+ where K : Borrow < Q > ,
1917
+ Q : Eq
1918
+ {
1919
+ self . from_hash ( hash, |q| q. borrow ( ) . eq ( k) )
1920
+ }
1921
+
1922
+ fn search < F > ( self , hash : u64 , is_match : F , compare_hashes : bool ) -> RawEntryMut < ' a , K , V , S >
1923
+ where for < ' b > F : FnMut ( & ' b K ) -> bool ,
1924
+ {
1925
+ match search_hashed_nonempty_mut ( & mut self . map . table ,
1926
+ SafeHash :: new ( hash) ,
1927
+ is_match,
1928
+ compare_hashes) {
1929
+ InternalEntry :: Occupied { elem } => {
1930
+ RawEntryMut :: Occupied ( RawOccupiedEntryMut { elem } )
1931
+ }
1932
+ InternalEntry :: Vacant { elem, .. } => {
1933
+ RawEntryMut :: Vacant ( RawVacantEntryMut {
1934
+ elem,
1935
+ hash_builder : & self . map . hash_builder ,
1936
+ } )
1937
+ }
1938
+ InternalEntry :: TableIsEmpty => {
1939
+ unreachable ! ( )
1940
+ }
1941
+ }
1942
+ }
1943
+ /// Create a `RawEntryMut` from the given hash.
1944
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1945
+ pub fn from_hash < F > ( self , hash : u64 , is_match : F ) -> RawEntryMut < ' a , K , V , S >
1946
+ where for < ' b > F : FnMut ( & ' b K ) -> bool ,
1947
+ {
1948
+ self . search ( hash, is_match, true )
1949
+ }
1950
+
1951
+ /// Search possible locations for an element with hash `hash` until `is_match` returns true for
1952
+ /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided
1953
+ /// hash.
1954
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1955
+ pub fn search_bucket < F > ( self , hash : u64 , is_match : F ) -> RawEntryMut < ' a , K , V , S >
1956
+ where for < ' b > F : FnMut ( & ' b K ) -> bool ,
1957
+ {
1958
+ self . search ( hash, is_match, false )
1959
+ }
1960
+ }
1961
+
1962
+ impl < ' a , K , V , S > RawEntryBuilder < ' a , K , V , S >
1963
+ where S : BuildHasher ,
1964
+ {
1965
+ /// Access an entry by key.
1966
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1967
+ pub fn from_key < Q : ?Sized > ( self , k : & Q ) -> Option < ( & ' a K , & ' a V ) >
1968
+ where K : Borrow < Q > ,
1969
+ Q : Hash + Eq
1970
+ {
1971
+ let mut hasher = self . map . hash_builder . build_hasher ( ) ;
1972
+ k. hash ( & mut hasher) ;
1973
+ self . from_key_hashed_nocheck ( hasher. finish ( ) , k)
1974
+ }
1975
+
1976
+ /// Access an entry by a key and its hash.
1977
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
1978
+ pub fn from_key_hashed_nocheck < Q : ?Sized > ( self , hash : u64 , k : & Q ) -> Option < ( & ' a K , & ' a V ) >
1979
+ where K : Borrow < Q > ,
1980
+ Q : Hash + Eq
1981
+
1982
+ {
1983
+ self . from_hash ( hash, |q| q. borrow ( ) . eq ( k) )
1984
+ }
1985
+
1986
+ fn search < F > ( self , hash : u64 , is_match : F , compare_hashes : bool ) -> Option < ( & ' a K , & ' a V ) >
1987
+ where F : FnMut ( & K ) -> bool
1988
+ {
1989
+ match search_hashed_nonempty ( & self . map . table ,
1990
+ SafeHash :: new ( hash) ,
1991
+ is_match,
1992
+ compare_hashes) {
1993
+ InternalEntry :: Occupied { elem } => Some ( elem. into_refs ( ) ) ,
1994
+ InternalEntry :: Vacant { .. } => None ,
1995
+ InternalEntry :: TableIsEmpty => unreachable ! ( ) ,
1996
+ }
1997
+ }
1998
+
1999
+ /// Access an entry by hash.
2000
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2001
+ pub fn from_hash < F > ( self , hash : u64 , is_match : F ) -> Option < ( & ' a K , & ' a V ) >
2002
+ where F : FnMut ( & K ) -> bool
2003
+ {
2004
+ self . search ( hash, is_match, true )
2005
+ }
2006
+
2007
+ /// Search possible locations for an element with hash `hash` until `is_match` returns true for
2008
+ /// one of them. There is no guarantee that all keys passed to `is_match` will have the provided
2009
+ /// hash.
2010
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2011
+ pub fn search_bucket < F > ( self , hash : u64 , is_match : F ) -> Option < ( & ' a K , & ' a V ) >
2012
+ where F : FnMut ( & K ) -> bool
2013
+ {
2014
+ self . search ( hash, is_match, false )
2015
+ }
2016
+ }
2017
+
2018
+ impl < ' a , K , V , S > RawEntryMut < ' a , K , V , S > {
2019
+ /// Ensures a value is in the entry by inserting the default if empty, and returns
2020
+ /// mutable references to the key and value in the entry.
2021
+ ///
2022
+ /// # Examples
2023
+ ///
2024
+ /// ```
2025
+ /// #![feature(hash_raw_entry)]
2026
+ /// use std::collections::HashMap;
2027
+ ///
2028
+ /// let mut map: HashMap<&str, u32> = HashMap::new();
2029
+ /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 12);
2030
+ ///
2031
+ /// assert_eq!(map["poneyland"], 12);
2032
+ ///
2033
+ /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 12).1 += 10;
2034
+ /// assert_eq!(map["poneyland"], 22);
2035
+ /// ```
2036
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2037
+ pub fn or_insert ( self , default_key : K , default_val : V ) -> ( & ' a mut K , & ' a mut V )
2038
+ where K : Hash ,
2039
+ S : BuildHasher ,
2040
+ {
2041
+ match self {
2042
+ RawEntryMut :: Occupied ( entry) => entry. into_key_value ( ) ,
2043
+ RawEntryMut :: Vacant ( entry) => entry. insert ( default_key, default_val) ,
2044
+ }
2045
+ }
2046
+
2047
+ /// Ensures a value is in the entry by inserting the result of the default function if empty,
2048
+ /// and returns mutable references to the key and value in the entry.
2049
+ ///
2050
+ /// # Examples
2051
+ ///
2052
+ /// ```
2053
+ /// #![feature(hash_raw_entry)]
2054
+ /// use std::collections::HashMap;
2055
+ ///
2056
+ /// let mut map: HashMap<&str, String> = HashMap::new();
2057
+ ///
2058
+ /// map.raw_entry_mut().from_key("poneyland").or_insert_with(|| {
2059
+ /// ("poneyland", "hoho".to_string())
2060
+ /// });
2061
+ ///
2062
+ /// assert_eq!(map["poneyland"], "hoho".to_string());
2063
+ /// ```
2064
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2065
+ pub fn or_insert_with < F > ( self , default : F ) -> ( & ' a mut K , & ' a mut V )
2066
+ where F : FnOnce ( ) -> ( K , V ) ,
2067
+ K : Hash ,
2068
+ S : BuildHasher ,
2069
+ {
2070
+ match self {
2071
+ RawEntryMut :: Occupied ( entry) => entry. into_key_value ( ) ,
2072
+ RawEntryMut :: Vacant ( entry) => {
2073
+ let ( k, v) = default ( ) ;
2074
+ entry. insert ( k, v)
2075
+ }
2076
+ }
2077
+ }
2078
+
2079
+ /// Provides in-place mutable access to an occupied entry before any
2080
+ /// potential inserts into the map.
2081
+ ///
2082
+ /// # Examples
2083
+ ///
2084
+ /// ```
2085
+ /// #![feature(hash_raw_entry)]
2086
+ /// use std::collections::HashMap;
2087
+ ///
2088
+ /// let mut map: HashMap<&str, u32> = HashMap::new();
2089
+ ///
2090
+ /// map.raw_entry_mut()
2091
+ /// .from_key("poneyland")
2092
+ /// .and_modify(|_k, v| { *v += 1 })
2093
+ /// .or_insert("poneyland", 42);
2094
+ /// assert_eq!(map["poneyland"], 42);
2095
+ ///
2096
+ /// map.raw_entry_mut()
2097
+ /// .from_key("poneyland")
2098
+ /// .and_modify(|_k, v| { *v += 1 })
2099
+ /// .or_insert("poneyland", 0);
2100
+ /// assert_eq!(map["poneyland"], 43);
2101
+ /// ```
2102
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2103
+ pub fn and_modify < F > ( self , f : F ) -> Self
2104
+ where F : FnOnce ( & mut K , & mut V )
2105
+ {
2106
+ match self {
2107
+ RawEntryMut :: Occupied ( mut entry) => {
2108
+ {
2109
+ let ( k, v) = entry. get_key_value_mut ( ) ;
2110
+ f ( k, v) ;
2111
+ }
2112
+ RawEntryMut :: Occupied ( entry)
2113
+ } ,
2114
+ RawEntryMut :: Vacant ( entry) => RawEntryMut :: Vacant ( entry) ,
2115
+ }
2116
+ }
2117
+ }
2118
+
2119
+ impl < ' a , K , V > RawOccupiedEntryMut < ' a , K , V > {
2120
+ /// Gets a reference to the key in the entry.
2121
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2122
+ pub fn key ( & self ) -> & K {
2123
+ self . elem . read ( ) . 0
2124
+ }
2125
+
2126
+ /// Gets a mutable reference to the key in the entry.
2127
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2128
+ pub fn key_mut ( & mut self ) -> & mut K {
2129
+ self . elem . read_mut ( ) . 0
2130
+ }
2131
+
2132
+ /// Converts the entry into a mutable reference to the key in the entry
2133
+ /// with a lifetime bound to the map itself.
2134
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2135
+ pub fn into_key ( self ) -> & ' a mut K {
2136
+ self . elem . into_mut_refs ( ) . 0
2137
+ }
2138
+
2139
+ /// Gets a reference to the value in the entry.
2140
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2141
+ pub fn get ( & self ) -> & V {
2142
+ self . elem . read ( ) . 1
2143
+ }
2144
+
2145
+ /// Converts the OccupiedEntry into a mutable reference to the value in the entry
2146
+ /// with a lifetime bound to the map itself.
2147
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2148
+ pub fn into_mut ( self ) -> & ' a mut V {
2149
+ self . elem . into_mut_refs ( ) . 1
2150
+ }
2151
+
2152
+ /// Gets a mutable reference to the value in the entry.
2153
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2154
+ pub fn get_mut ( & mut self ) -> & mut V {
2155
+ self . elem . read_mut ( ) . 1
2156
+ }
2157
+
2158
+ /// Gets a reference to the key and value in the entry.
2159
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2160
+ pub fn get_key_value ( & mut self ) -> ( & K , & V ) {
2161
+ self . elem . read ( )
2162
+ }
2163
+
2164
+ /// Gets a mutable reference to the key and value in the entry.
2165
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2166
+ pub fn get_key_value_mut ( & mut self ) -> ( & mut K , & mut V ) {
2167
+ self . elem . read_mut ( )
2168
+ }
2169
+
2170
+ /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry
2171
+ /// with a lifetime bound to the map itself.
2172
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2173
+ pub fn into_key_value ( self ) -> ( & ' a mut K , & ' a mut V ) {
2174
+ self . elem . into_mut_refs ( )
2175
+ }
2176
+
2177
+ /// Sets the value of the entry, and returns the entry's old value.
2178
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2179
+ pub fn insert ( & mut self , value : V ) -> V {
2180
+ mem:: replace ( self . get_mut ( ) , value)
2181
+ }
2182
+
2183
+ /// Sets the value of the entry, and returns the entry's old value.
2184
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2185
+ pub fn insert_key ( & mut self , key : K ) -> K {
2186
+ mem:: replace ( self . key_mut ( ) , key)
2187
+ }
2188
+
2189
+ /// Takes the value out of the entry, and returns it.
2190
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2191
+ pub fn remove ( self ) -> V {
2192
+ pop_internal ( self . elem ) . 1
2193
+ }
2194
+
2195
+ /// Take the ownership of the key and value from the map.
2196
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2197
+ pub fn remove_entry ( self ) -> ( K , V ) {
2198
+ let ( k, v, _) = pop_internal ( self . elem ) ;
2199
+ ( k, v)
2200
+ }
2201
+ }
2202
+
2203
+ impl < ' a , K , V , S > RawVacantEntryMut < ' a , K , V , S > {
2204
+ /// Sets the value of the entry with the VacantEntry's key,
2205
+ /// and returns a mutable reference to it.
2206
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2207
+ pub fn insert ( self , key : K , value : V ) -> ( & ' a mut K , & ' a mut V )
2208
+ where K : Hash ,
2209
+ S : BuildHasher ,
2210
+ {
2211
+ let mut hasher = self . hash_builder . build_hasher ( ) ;
2212
+ key. hash ( & mut hasher) ;
2213
+ self . insert_hashed_nocheck ( hasher. finish ( ) , key, value)
2214
+ }
2215
+
2216
+ /// Sets the value of the entry with the VacantEntry's key,
2217
+ /// and returns a mutable reference to it.
2218
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2219
+ pub fn insert_hashed_nocheck ( self , hash : u64 , key : K , value : V ) -> ( & ' a mut K , & ' a mut V ) {
2220
+ let hash = SafeHash :: new ( hash) ;
2221
+ let b = match self . elem {
2222
+ NeqElem ( mut bucket, disp) => {
2223
+ if disp >= DISPLACEMENT_THRESHOLD {
2224
+ bucket. table_mut ( ) . set_tag ( true ) ;
2225
+ }
2226
+ robin_hood ( bucket, disp, hash, key, value)
2227
+ } ,
2228
+ NoElem ( mut bucket, disp) => {
2229
+ if disp >= DISPLACEMENT_THRESHOLD {
2230
+ bucket. table_mut ( ) . set_tag ( true ) ;
2231
+ }
2232
+ bucket. put ( hash, key, value)
2233
+ } ,
2234
+ } ;
2235
+ b. into_mut_refs ( )
2236
+ }
2237
+ }
2238
+
2239
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2240
+ impl < ' a , K , V , S > Debug for RawEntryBuilderMut < ' a , K , V , S > {
2241
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2242
+ f. debug_struct ( "RawEntryBuilder" )
2243
+ . finish ( )
2244
+ }
2245
+ }
2246
+
2247
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2248
+ impl < ' a , K : Debug , V : Debug , S > Debug for RawEntryMut < ' a , K , V , S > {
2249
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2250
+ match * self {
2251
+ RawEntryMut :: Vacant ( ref v) => {
2252
+ f. debug_tuple ( "RawEntry" )
2253
+ . field ( v)
2254
+ . finish ( )
2255
+ }
2256
+ RawEntryMut :: Occupied ( ref o) => {
2257
+ f. debug_tuple ( "RawEntry" )
2258
+ . field ( o)
2259
+ . finish ( )
2260
+ }
2261
+ }
2262
+ }
2263
+ }
2264
+
2265
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2266
+ impl < ' a , K : Debug , V : Debug > Debug for RawOccupiedEntryMut < ' a , K , V > {
2267
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2268
+ f. debug_struct ( "RawOccupiedEntryMut" )
2269
+ . field ( "key" , self . key ( ) )
2270
+ . field ( "value" , self . get ( ) )
2271
+ . finish ( )
2272
+ }
2273
+ }
2274
+
2275
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2276
+ impl < ' a , K , V , S > Debug for RawVacantEntryMut < ' a , K , V , S > {
2277
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2278
+ f. debug_struct ( "RawVacantEntryMut" )
2279
+ . finish ( )
2280
+ }
2281
+ }
2282
+
2283
+ #[ unstable( feature = "hash_raw_entry" , issue = "54043" ) ]
2284
+ impl < ' a , K , V , S > Debug for RawEntryBuilder < ' a , K , V , S > {
2285
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2286
+ f. debug_struct ( "RawEntryBuilder" )
2287
+ . finish ( )
2288
+ }
2289
+ }
2290
+
1727
2291
/// A view into a single entry in a map, which may either be vacant or occupied.
1728
2292
///
1729
2293
/// This `enum` is constructed from the [`entry`] method on [`HashMap`].
@@ -3681,4 +4245,106 @@ mod test_map {
3681
4245
}
3682
4246
}
3683
4247
4248
+ #[ test]
4249
+ fn test_raw_entry ( ) {
4250
+ use super :: RawEntryMut :: { Occupied , Vacant } ;
4251
+
4252
+ let xs = [ ( 1i32 , 10i32 ) , ( 2 , 20 ) , ( 3 , 30 ) , ( 4 , 40 ) , ( 5 , 50 ) , ( 6 , 60 ) ] ;
4253
+
4254
+ let mut map: HashMap < _ , _ > = xs. iter ( ) . cloned ( ) . collect ( ) ;
4255
+
4256
+ let compute_hash = |map : & HashMap < i32 , i32 > , k : i32 | -> u64 {
4257
+ use core:: hash:: { BuildHasher , Hash , Hasher } ;
4258
+
4259
+ let mut hasher = map. hasher ( ) . build_hasher ( ) ;
4260
+ k. hash ( & mut hasher) ;
4261
+ hasher. finish ( )
4262
+ } ;
4263
+
4264
+ // Existing key (insert)
4265
+ match map. raw_entry_mut ( ) . from_key ( & 1 ) {
4266
+ Vacant ( _) => unreachable ! ( ) ,
4267
+ Occupied ( mut view) => {
4268
+ assert_eq ! ( view. get( ) , & 10 ) ;
4269
+ assert_eq ! ( view. insert( 100 ) , 10 ) ;
4270
+ }
4271
+ }
4272
+ let hash1 = compute_hash ( & map, 1 ) ;
4273
+ assert_eq ! ( map. raw_entry( ) . from_key( & 1 ) . unwrap( ) , ( & 1 , & 100 ) ) ;
4274
+ assert_eq ! ( map. raw_entry( ) . from_hash( hash1, |k| * k == 1 ) . unwrap( ) , ( & 1 , & 100 ) ) ;
4275
+ assert_eq ! ( map. raw_entry( ) . from_key_hashed_nocheck( hash1, & 1 ) . unwrap( ) , ( & 1 , & 100 ) ) ;
4276
+ assert_eq ! ( map. raw_entry( ) . search_bucket( hash1, |k| * k == 1 ) . unwrap( ) , ( & 1 , & 100 ) ) ;
4277
+ assert_eq ! ( map. len( ) , 6 ) ;
4278
+
4279
+ // Existing key (update)
4280
+ match map. raw_entry_mut ( ) . from_key ( & 2 ) {
4281
+ Vacant ( _) => unreachable ! ( ) ,
4282
+ Occupied ( mut view) => {
4283
+ let v = view. get_mut ( ) ;
4284
+ let new_v = ( * v) * 10 ;
4285
+ * v = new_v;
4286
+ }
4287
+ }
4288
+ let hash2 = compute_hash ( & map, 2 ) ;
4289
+ assert_eq ! ( map. raw_entry( ) . from_key( & 2 ) . unwrap( ) , ( & 2 , & 200 ) ) ;
4290
+ assert_eq ! ( map. raw_entry( ) . from_hash( hash2, |k| * k == 2 ) . unwrap( ) , ( & 2 , & 200 ) ) ;
4291
+ assert_eq ! ( map. raw_entry( ) . from_key_hashed_nocheck( hash2, & 2 ) . unwrap( ) , ( & 2 , & 200 ) ) ;
4292
+ assert_eq ! ( map. raw_entry( ) . search_bucket( hash2, |k| * k == 2 ) . unwrap( ) , ( & 2 , & 200 ) ) ;
4293
+ assert_eq ! ( map. len( ) , 6 ) ;
4294
+
4295
+ // Existing key (take)
4296
+ let hash3 = compute_hash ( & map, 3 ) ;
4297
+ match map. raw_entry_mut ( ) . from_key_hashed_nocheck ( hash3, & 3 ) {
4298
+ Vacant ( _) => unreachable ! ( ) ,
4299
+ Occupied ( view) => {
4300
+ assert_eq ! ( view. remove_entry( ) , ( 3 , 30 ) ) ;
4301
+ }
4302
+ }
4303
+ assert_eq ! ( map. raw_entry( ) . from_key( & 3 ) , None ) ;
4304
+ assert_eq ! ( map. raw_entry( ) . from_hash( hash3, |k| * k == 3 ) , None ) ;
4305
+ assert_eq ! ( map. raw_entry( ) . from_key_hashed_nocheck( hash3, & 3 ) , None ) ;
4306
+ assert_eq ! ( map. raw_entry( ) . search_bucket( hash3, |k| * k == 3 ) , None ) ;
4307
+ assert_eq ! ( map. len( ) , 5 ) ;
4308
+
4309
+
4310
+ // Nonexistent key (insert)
4311
+ match map. raw_entry_mut ( ) . from_key ( & 10 ) {
4312
+ Occupied ( _) => unreachable ! ( ) ,
4313
+ Vacant ( view) => {
4314
+ assert_eq ! ( view. insert( 10 , 1000 ) , ( & mut 10 , & mut 1000 ) ) ;
4315
+ }
4316
+ }
4317
+ assert_eq ! ( map. raw_entry( ) . from_key( & 10 ) . unwrap( ) , ( & 10 , & 1000 ) ) ;
4318
+ assert_eq ! ( map. len( ) , 6 ) ;
4319
+
4320
+ // Ensure all lookup methods produce equivalent results.
4321
+ for k in 0 ..12 {
4322
+ let hash = compute_hash ( & map, k) ;
4323
+ let v = map. get ( & k) . cloned ( ) ;
4324
+ let kv = v. as_ref ( ) . map ( |v| ( & k, v) ) ;
4325
+
4326
+ assert_eq ! ( map. raw_entry( ) . from_key( & k) , kv) ;
4327
+ assert_eq ! ( map. raw_entry( ) . from_hash( hash, |q| * q == k) , kv) ;
4328
+ assert_eq ! ( map. raw_entry( ) . from_key_hashed_nocheck( hash, & k) , kv) ;
4329
+ assert_eq ! ( map. raw_entry( ) . search_bucket( hash, |q| * q == k) , kv) ;
4330
+
4331
+ match map. raw_entry_mut ( ) . from_key ( & k) {
4332
+ Occupied ( mut o) => assert_eq ! ( Some ( o. get_key_value( ) ) , kv) ,
4333
+ Vacant ( _) => assert_eq ! ( v, None ) ,
4334
+ }
4335
+ match map. raw_entry_mut ( ) . from_key_hashed_nocheck ( hash, & k) {
4336
+ Occupied ( mut o) => assert_eq ! ( Some ( o. get_key_value( ) ) , kv) ,
4337
+ Vacant ( _) => assert_eq ! ( v, None ) ,
4338
+ }
4339
+ match map. raw_entry_mut ( ) . from_hash ( hash, |q| * q == k) {
4340
+ Occupied ( mut o) => assert_eq ! ( Some ( o. get_key_value( ) ) , kv) ,
4341
+ Vacant ( _) => assert_eq ! ( v, None ) ,
4342
+ }
4343
+ match map. raw_entry_mut ( ) . search_bucket ( hash, |q| * q == k) {
4344
+ Occupied ( mut o) => assert_eq ! ( Some ( o. get_key_value( ) ) , kv) ,
4345
+ Vacant ( _) => assert_eq ! ( v, None ) ,
4346
+ }
4347
+ }
4348
+ }
4349
+
3684
4350
}
0 commit comments