Skip to content

Commit cb5ee7c

Browse files
committed
Add implementations of ops for BTreeSet that keep ownership
1 parent c09d35d commit cb5ee7c

File tree

1 file changed

+116
-0
lines changed
  • library/alloc/src/collections/btree

1 file changed

+116
-0
lines changed

library/alloc/src/collections/btree/set.rs

+116
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,37 @@ impl<T: Ord + Clone, A: Allocator + Clone> Sub<&BTreeSet<T, A>> for &BTreeSet<T,
14041404
}
14051405
}
14061406

1407+
#[stable(feature = "set_owned_ops", since = "CURRENT_RUSTC_VERSION")]
1408+
impl<T: Ord, A: Allocator + Clone> Sub<&BTreeSet<T, A>> for BTreeSet<T, A> {
1409+
type Output = BTreeSet<T, A>;
1410+
1411+
/// Returns the difference of `self` and `rhs` as a new `BTreeSet<T>`.
1412+
///
1413+
/// # Examples
1414+
///
1415+
/// ```
1416+
/// use std::collections::BTreeSet;
1417+
///
1418+
/// let a = BTreeSet::from([1, 2, 3]);
1419+
/// let b = BTreeSet::from([3, 4, 5]);
1420+
///
1421+
/// let result = a - &b;
1422+
/// assert_eq!(result, BTreeSet::from([1, 2]));
1423+
/// ```
1424+
fn sub(mut self, rhs: &BTreeSet<T, A>) -> BTreeSet<T, A> {
1425+
// Iterate the smaller set, removing elements that are in `rhs` from `self`
1426+
if self.len() <= rhs.len() {
1427+
self.retain(|e| !rhs.contains(e));
1428+
} else {
1429+
rhs.iter().for_each(|e| {
1430+
self.remove(e);
1431+
})
1432+
}
1433+
1434+
self
1435+
}
1436+
}
1437+
14071438
#[stable(feature = "rust1", since = "1.0.0")]
14081439
impl<T: Ord + Clone, A: Allocator + Clone> BitXor<&BTreeSet<T, A>> for &BTreeSet<T, A> {
14091440
type Output = BTreeSet<T, A>;
@@ -1429,6 +1460,37 @@ impl<T: Ord + Clone, A: Allocator + Clone> BitXor<&BTreeSet<T, A>> for &BTreeSet
14291460
}
14301461
}
14311462

1463+
#[stable(feature = "set_owned_ops", since = "CURRENT_RUSTC_VERSION")]
1464+
impl<T: Ord, A: Allocator + Clone> BitXor<BTreeSet<T, A>> for BTreeSet<T, A> {
1465+
type Output = BTreeSet<T, A>;
1466+
1467+
/// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet<T>`.
1468+
///
1469+
/// # Examples
1470+
///
1471+
/// ```
1472+
/// use std::collections::BTreeSet;
1473+
///
1474+
/// let a = BTreeSet::from([1, 2, 3]);
1475+
/// let b = BTreeSet::from([2, 3, 4]);
1476+
///
1477+
/// let result = a ^ b;
1478+
/// assert_eq!(result, BTreeSet::from([1, 4]));
1479+
/// ```
1480+
fn bitxor(self, rhs: BTreeSet<T, A>) -> BTreeSet<T, A> {
1481+
// Iterate through the smaller set
1482+
let [mut a, mut b] = minmax_by_key(self, rhs, BTreeSet::len);
1483+
1484+
// This is essentially
1485+
// a = a - b (retain elements that are *not* in b)
1486+
// b = b - a (remove all elements that are in a)
1487+
a.retain(|e| !b.remove(e));
1488+
1489+
// Union of the differences
1490+
a | b
1491+
}
1492+
}
1493+
14321494
#[stable(feature = "rust1", since = "1.0.0")]
14331495
impl<T: Ord + Clone, A: Allocator + Clone> BitAnd<&BTreeSet<T, A>> for &BTreeSet<T, A> {
14341496
type Output = BTreeSet<T, A>;
@@ -1454,6 +1516,29 @@ impl<T: Ord + Clone, A: Allocator + Clone> BitAnd<&BTreeSet<T, A>> for &BTreeSet
14541516
}
14551517
}
14561518

1519+
#[stable(feature = "set_owned_ops", since = "CURRENT_RUSTC_VERSION")]
1520+
impl<T: Ord, A: Allocator + Clone> BitAnd<&BTreeSet<T, A>> for BTreeSet<T, A> {
1521+
type Output = BTreeSet<T, A>;
1522+
1523+
/// Returns the intersection of `self` and `rhs` as a new `BTreeSet<T>`.
1524+
///
1525+
/// # Examples
1526+
///
1527+
/// ```
1528+
/// use std::collections::BTreeSet;
1529+
///
1530+
/// let a = BTreeSet::from([1, 2, 3]);
1531+
/// let b = BTreeSet::from([2, 3, 4]);
1532+
///
1533+
/// let result = a & &b;
1534+
/// assert_eq!(result, BTreeSet::from([2, 3]));
1535+
/// ```
1536+
fn bitand(mut self, rhs: &BTreeSet<T, A>) -> BTreeSet<T, A> {
1537+
self.retain(|e| rhs.contains(e));
1538+
self
1539+
}
1540+
}
1541+
14571542
#[stable(feature = "rust1", since = "1.0.0")]
14581543
impl<T: Ord + Clone, A: Allocator + Clone> BitOr<&BTreeSet<T, A>> for &BTreeSet<T, A> {
14591544
type Output = BTreeSet<T, A>;
@@ -1479,6 +1564,33 @@ impl<T: Ord + Clone, A: Allocator + Clone> BitOr<&BTreeSet<T, A>> for &BTreeSet<
14791564
}
14801565
}
14811566

1567+
#[stable(feature = "set_owned_ops", since = "CURRENT_RUSTC_VERSION")]
1568+
impl<T: Ord, A: Allocator + Clone> BitOr<BTreeSet<T, A>> for BTreeSet<T, A> {
1569+
type Output = BTreeSet<T, A>;
1570+
1571+
/// Returns the union of `self` and `rhs` as a new `BTreeSet<T>`.
1572+
///
1573+
/// # Examples
1574+
///
1575+
/// ```
1576+
/// use std::collections::BTreeSet;
1577+
///
1578+
/// let a = BTreeSet::from([1, 2, 3]);
1579+
/// let b = BTreeSet::from([3, 4, 5]);
1580+
///
1581+
/// let result = a | b;
1582+
/// assert_eq!(result, BTreeSet::from([1, 2, 3, 4, 5]));
1583+
/// ```
1584+
fn bitor(self, rhs: BTreeSet<T, A>) -> BTreeSet<T, A> {
1585+
// Try to avoid unnecessary moves, by keeping set with the bigger length
1586+
let [a, mut b] = minmax_by_key(self, rhs, BTreeSet::len);
1587+
1588+
b.extend(a);
1589+
1590+
b
1591+
}
1592+
}
1593+
14821594
#[stable(feature = "rust1", since = "1.0.0")]
14831595
impl<T: Debug, A: Allocator + Clone> Debug for BTreeSet<T, A> {
14841596
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -1789,5 +1901,9 @@ impl<'a, T: Ord> Iterator for Union<'a, T> {
17891901
#[stable(feature = "fused", since = "1.26.0")]
17901902
impl<T: Ord> FusedIterator for Union<'_, T> {}
17911903

1904+
fn minmax_by_key<T, K: Ord>(a: T, b: T, k: impl Fn(&T) -> K) -> [T; 2] {
1905+
if k(&a) <= k(&b) { [a, b] } else { [b, a] }
1906+
}
1907+
17921908
#[cfg(test)]
17931909
mod tests;

0 commit comments

Comments
 (0)