@@ -1147,6 +1147,38 @@ where
11471147 }
11481148}
11491149
1150+ #[ stable( feature = "set_owned_ops" , since = "CURRENT_RUSTC_VERSION" ) ]
1151+ impl < T , S > BitOr < HashSet < T , S > > for HashSet < T , S >
1152+ where
1153+ T : Eq + Hash ,
1154+ S : BuildHasher ,
1155+ {
1156+ type Output = HashSet < T , S > ;
1157+
1158+ /// Returns the union of `self` and `rhs` as a new `HashSet<T, S>`.
1159+ ///
1160+ /// # Examples
1161+ ///
1162+ /// ```
1163+ /// use std::collections::HashSet;
1164+ ///
1165+ /// let a = HashSet::from([1, 2, 3]);
1166+ /// let b = HashSet::from([3, 4, 5]);
1167+ ///
1168+ /// let result = a | b;
1169+ /// assert_eq!(result, HashSet::from([1, 2, 3, 4, 5]));
1170+ /// ```
1171+ fn bitor ( self , rhs : HashSet < T , S > ) -> HashSet < T , S > {
1172+ // Try to avoid allocations by keeping set with the bigger capacity,
1173+ // try to avoid unnecessary moves, by keeping set with the bigger length
1174+ let [ a, mut b] = minmax_by_key ( self , rhs, |set| ( set. capacity ( ) , set. len ( ) ) ) ;
1175+
1176+ b. extend ( a) ;
1177+
1178+ b
1179+ }
1180+ }
1181+
11501182#[ stable( feature = "rust1" , since = "1.0.0" ) ]
11511183impl < T , S > BitAnd < & HashSet < T , S > > for & HashSet < T , S >
11521184where
@@ -1173,6 +1205,33 @@ where
11731205 }
11741206}
11751207
1208+ #[ stable( feature = "set_owned_ops" , since = "CURRENT_RUSTC_VERSION" ) ]
1209+ impl < T , S > BitAnd < & HashSet < T , S > > for HashSet < T , S >
1210+ where
1211+ T : Eq + Hash ,
1212+ S : BuildHasher ,
1213+ {
1214+ type Output = HashSet < T , S > ;
1215+
1216+ /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, S>`.
1217+ ///
1218+ /// # Examples
1219+ ///
1220+ /// ```
1221+ /// use std::collections::HashSet;
1222+ ///
1223+ /// let a = HashSet::from([1, 2, 3]);
1224+ /// let b = HashSet::from([2, 3, 4]);
1225+ ///
1226+ /// let result = a & &b;
1227+ /// assert_eq!(result, HashSet::from([2, 3]));
1228+ /// ```
1229+ fn bitand ( mut self , rhs : & HashSet < T , S > ) -> HashSet < T , S > {
1230+ self . retain ( |e| rhs. contains ( e) ) ;
1231+ self
1232+ }
1233+ }
1234+
11761235#[ stable( feature = "rust1" , since = "1.0.0" ) ]
11771236impl < T , S > BitXor < & HashSet < T , S > > for & HashSet < T , S >
11781237where
@@ -1199,6 +1258,41 @@ where
11991258 }
12001259}
12011260
1261+ #[ stable( feature = "set_owned_ops" , since = "CURRENT_RUSTC_VERSION" ) ]
1262+ impl < T , S > BitXor < HashSet < T , S > > for HashSet < T , S >
1263+ where
1264+ T : Eq + Hash ,
1265+ S : BuildHasher ,
1266+ {
1267+ type Output = HashSet < T , S > ;
1268+
1269+ /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, S>`.
1270+ ///
1271+ /// # Examples
1272+ ///
1273+ /// ```
1274+ /// use std::collections::HashSet;
1275+ ///
1276+ /// let a = HashSet::from([1, 2, 3]);
1277+ /// let b = HashSet::from([3, 4, 5]);
1278+ ///
1279+ /// let result = a ^ b;
1280+ /// assert_eq!(result, HashSet::from([1, 2, 4, 5]));
1281+ /// ```
1282+ fn bitxor ( self , rhs : HashSet < T , S > ) -> HashSet < T , S > {
1283+ // Iterate through the smaller set
1284+ let [ mut a, mut b] = minmax_by_key ( self , rhs, HashSet :: len) ;
1285+
1286+ // This is essentially
1287+ // a = a - b (retain elements that are *not* in b)
1288+ // b = b - a (remove all elements that are in a)
1289+ a. retain ( |e| !b. remove ( e) ) ;
1290+
1291+ // Union of the differences
1292+ a | b
1293+ }
1294+ }
1295+
12021296#[ stable( feature = "rust1" , since = "1.0.0" ) ]
12031297impl < T , S > Sub < & HashSet < T , S > > for & HashSet < T , S >
12041298where
@@ -1225,6 +1319,41 @@ where
12251319 }
12261320}
12271321
1322+ #[ stable( feature = "set_owned_ops" , since = "CURRENT_RUSTC_VERSION" ) ]
1323+ impl < T , S > Sub < & HashSet < T , S > > for HashSet < T , S >
1324+ where
1325+ T : Eq + Hash ,
1326+ S : BuildHasher ,
1327+ {
1328+ type Output = HashSet < T , S > ;
1329+
1330+ /// Returns the difference of `self` and `rhs` as a new `HashSet<T, S>`.
1331+ ///
1332+ /// # Examples
1333+ ///
1334+ /// ```
1335+ /// use std::collections::HashSet;
1336+ ///
1337+ /// let a = HashSet::from([1, 2, 3]);
1338+ /// let b = HashSet::from([3, 4, 5]);
1339+ ///
1340+ /// let result = a - &b;
1341+ /// assert_eq!(result, HashSet::from([1, 2]));
1342+ /// ```
1343+ fn sub ( mut self , rhs : & HashSet < T , S > ) -> HashSet < T , S > {
1344+ // Iterate the smaller set, removing elements that are in `rhs` from `self`
1345+ if self . len ( ) <= rhs. len ( ) {
1346+ self . retain ( |e| !rhs. contains ( e) ) ;
1347+ } else {
1348+ rhs. iter ( ) . for_each ( |e| {
1349+ self . remove ( e) ;
1350+ } )
1351+ }
1352+
1353+ self
1354+ }
1355+ }
1356+
12281357/// An iterator over the items of a `HashSet`.
12291358///
12301359/// This `struct` is created by the [`iter`] method on [`HashSet`].
@@ -1885,3 +2014,7 @@ fn assert_covariance() {
18852014 d
18862015 }
18872016}
2017+
2018+ fn minmax_by_key < T , K : Ord > ( a : T , b : T , k : impl Fn ( & T ) -> K ) -> [ T ; 2 ] {
2019+ if k ( & a) <= k ( & b) { [ a, b] } else { [ b, a] }
2020+ }
0 commit comments