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