1
1
use crate :: { Equivalent , TryReserveError } ;
2
- use alloc:: borrow:: ToOwned ;
3
2
use core:: hash:: { BuildHasher , Hash } ;
4
3
use core:: iter:: { Chain , FusedIterator } ;
5
4
use core:: ops:: { BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Sub , SubAssign } ;
@@ -911,45 +910,16 @@ where
911
910
/// ```
912
911
#[ cfg_attr( feature = "inline-more" , inline) ]
913
912
pub fn get_or_insert ( & mut self , value : T ) -> & T {
914
- // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
915
- // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
916
- self . map
917
- . raw_entry_mut ( )
918
- . from_key ( & value)
919
- . or_insert ( value, ( ) )
920
- . 0
921
- }
922
-
923
- /// Inserts an owned copy of the given `value` into the set if it is not
924
- /// present, then returns a reference to the value in the set.
925
- ///
926
- /// # Examples
927
- ///
928
- /// ```
929
- /// use hashbrown::HashSet;
930
- ///
931
- /// let mut set: HashSet<String> = ["cat", "dog", "horse"]
932
- /// .iter().map(|&pet| pet.to_owned()).collect();
933
- ///
934
- /// assert_eq!(set.len(), 3);
935
- /// for &pet in &["cat", "dog", "fish"] {
936
- /// let value = set.get_or_insert_owned(pet);
937
- /// assert_eq!(value, pet);
938
- /// }
939
- /// assert_eq!(set.len(), 4); // a new "fish" was inserted
940
- /// ```
941
- #[ inline]
942
- pub fn get_or_insert_owned < Q > ( & mut self , value : & Q ) -> & T
943
- where
944
- Q : Hash + Equivalent < T > + ToOwned < Owned = T > + ?Sized ,
945
- {
946
- // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
947
- // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
948
- self . map
949
- . raw_entry_mut ( )
950
- . from_key ( value)
951
- . or_insert_with ( || ( value. to_owned ( ) , ( ) ) )
952
- . 0
913
+ let hash = make_hash ( & self . map . hash_builder , & value) ;
914
+ let bucket = match self . map . table . find_or_find_insert_slot (
915
+ hash,
916
+ equivalent_key ( & value) ,
917
+ make_hasher ( & self . map . hash_builder ) ,
918
+ ) {
919
+ Ok ( bucket) => bucket,
920
+ Err ( slot) => unsafe { self . map . table . insert_in_slot ( hash, slot, ( value, ( ) ) ) } ,
921
+ } ;
922
+ unsafe { & bucket. as_ref ( ) . 0 }
953
923
}
954
924
955
925
/// Inserts a value computed from `f` into the set if the given `value` is
@@ -970,19 +940,33 @@ where
970
940
/// }
971
941
/// assert_eq!(set.len(), 4); // a new "fish" was inserted
972
942
/// ```
943
+ ///
944
+ /// The following example will panic because the new value doesn't match.
945
+ ///
946
+ /// ```should_panic
947
+ /// let mut set = hashbrown::HashSet::new();
948
+ /// set.get_or_insert_with("rust", |_| String::new());
949
+ /// ```
973
950
#[ cfg_attr( feature = "inline-more" , inline) ]
974
951
pub fn get_or_insert_with < Q , F > ( & mut self , value : & Q , f : F ) -> & T
975
952
where
976
953
Q : Hash + Equivalent < T > + ?Sized ,
977
954
F : FnOnce ( & Q ) -> T ,
978
955
{
979
- // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
980
- // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
981
- self . map
982
- . raw_entry_mut ( )
983
- . from_key ( value)
984
- . or_insert_with ( || ( f ( value) , ( ) ) )
985
- . 0
956
+ let hash = make_hash ( & self . map . hash_builder , & value) ;
957
+ let bucket = match self . map . table . find_or_find_insert_slot (
958
+ hash,
959
+ equivalent_key ( value) ,
960
+ make_hasher ( & self . map . hash_builder ) ,
961
+ ) {
962
+ Ok ( bucket) => bucket,
963
+ Err ( slot) => {
964
+ let new = f ( value) ;
965
+ assert ! ( value. equivalent( & new) , "new value is not equivalent" ) ;
966
+ unsafe { self . map . table . insert_in_slot ( hash, slot, ( new, ( ) ) ) }
967
+ }
968
+ } ;
969
+ unsafe { & bucket. as_ref ( ) . 0 }
986
970
}
987
971
988
972
/// Gets the given value's corresponding entry in the set for in-place manipulation.
@@ -1597,15 +1581,21 @@ where
1597
1581
/// ```
1598
1582
fn bitxor_assign ( & mut self , rhs : & HashSet < T , S , A > ) {
1599
1583
for item in rhs {
1600
- let entry = self . map . raw_entry_mut ( ) . from_key ( item) ;
1601
- match entry {
1602
- map:: RawEntryMut :: Occupied ( e) => {
1603
- e. remove ( ) ;
1604
- }
1605
- map:: RawEntryMut :: Vacant ( e) => {
1606
- e. insert ( item. to_owned ( ) , ( ) ) ;
1607
- }
1608
- } ;
1584
+ let hash = make_hash ( & self . map . hash_builder , & item) ;
1585
+ match self . map . table . find_or_find_insert_slot (
1586
+ hash,
1587
+ equivalent_key ( item) ,
1588
+ make_hasher ( & self . map . hash_builder ) ,
1589
+ ) {
1590
+ Ok ( bucket) => unsafe {
1591
+ self . map . table . remove ( bucket) ;
1592
+ } ,
1593
+ Err ( slot) => unsafe {
1594
+ self . map
1595
+ . table
1596
+ . insert_in_slot ( hash, slot, ( item. clone ( ) , ( ) ) ) ;
1597
+ } ,
1598
+ }
1609
1599
}
1610
1600
}
1611
1601
}
0 commit comments