11use crate :: { Equivalent , TryReserveError } ;
2- use alloc:: borrow:: ToOwned ;
32use core:: hash:: { BuildHasher , Hash } ;
43use core:: iter:: { Chain , FusedIterator } ;
54use core:: ops:: { BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Sub , SubAssign } ;
@@ -911,45 +910,16 @@ where
911910 /// ```
912911 #[ cfg_attr( feature = "inline-more" , inline) ]
913912 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 }
953923 }
954924
955925 /// Inserts a value computed from `f` into the set if the given `value` is
@@ -970,19 +940,33 @@ where
970940 /// }
971941 /// assert_eq!(set.len(), 4); // a new "fish" was inserted
972942 /// ```
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+ /// ```
973950 #[ cfg_attr( feature = "inline-more" , inline) ]
974951 pub fn get_or_insert_with < Q , F > ( & mut self , value : & Q , f : F ) -> & T
975952 where
976953 Q : Hash + Equivalent < T > + ?Sized ,
977954 F : FnOnce ( & Q ) -> T ,
978955 {
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 }
986970 }
987971
988972 /// Gets the given value's corresponding entry in the set for in-place manipulation.
@@ -1597,15 +1581,21 @@ where
15971581 /// ```
15981582 fn bitxor_assign ( & mut self , rhs : & HashSet < T , S , A > ) {
15991583 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+ }
16091599 }
16101600 }
16111601}
0 commit comments