Skip to content

Commit 80b47a3

Browse files
committed
Add implementations of ops for BTreeSet that keep ownership
1 parent a2df222 commit 80b47a3

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
@@ -1545,6 +1545,37 @@ impl<T: Ord + Clone, A: Allocator + Clone> Sub<&BTreeSet<T, A>> for &BTreeSet<T,
15451545
}
15461546
}
15471547

1548+
#[stable(feature = "set_owned_ops", since = "CURRENT_RUSTC_VERSION")]
1549+
impl<T: Ord, A: Allocator + Clone> Sub<&BTreeSet<T, A>> for BTreeSet<T, A> {
1550+
type Output = BTreeSet<T, A>;
1551+
1552+
/// Returns the difference of `self` and `rhs` as a new `BTreeSet<T>`.
1553+
///
1554+
/// # Examples
1555+
///
1556+
/// ```
1557+
/// use std::collections::BTreeSet;
1558+
///
1559+
/// let a = BTreeSet::from([1, 2, 3]);
1560+
/// let b = BTreeSet::from([3, 4, 5]);
1561+
///
1562+
/// let result = a - &b;
1563+
/// assert_eq!(result, BTreeSet::from([1, 2]));
1564+
/// ```
1565+
fn sub(mut self, rhs: &BTreeSet<T, A>) -> BTreeSet<T, A> {
1566+
// Iterate the smaller set, removing elements that are in `rhs` from `self`
1567+
if self.len() <= rhs.len() {
1568+
self.retain(|e| !rhs.contains(e));
1569+
} else {
1570+
rhs.iter().for_each(|e| {
1571+
self.remove(e);
1572+
})
1573+
}
1574+
1575+
self
1576+
}
1577+
}
1578+
15481579
#[stable(feature = "rust1", since = "1.0.0")]
15491580
impl<T: Ord + Clone, A: Allocator + Clone> BitXor<&BTreeSet<T, A>> for &BTreeSet<T, A> {
15501581
type Output = BTreeSet<T, A>;
@@ -1570,6 +1601,37 @@ impl<T: Ord + Clone, A: Allocator + Clone> BitXor<&BTreeSet<T, A>> for &BTreeSet
15701601
}
15711602
}
15721603

1604+
#[stable(feature = "set_owned_ops", since = "CURRENT_RUSTC_VERSION")]
1605+
impl<T: Ord, A: Allocator + Clone> BitXor<BTreeSet<T, A>> for BTreeSet<T, A> {
1606+
type Output = BTreeSet<T, A>;
1607+
1608+
/// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet<T>`.
1609+
///
1610+
/// # Examples
1611+
///
1612+
/// ```
1613+
/// use std::collections::BTreeSet;
1614+
///
1615+
/// let a = BTreeSet::from([1, 2, 3]);
1616+
/// let b = BTreeSet::from([2, 3, 4]);
1617+
///
1618+
/// let result = a ^ b;
1619+
/// assert_eq!(result, BTreeSet::from([1, 4]));
1620+
/// ```
1621+
fn bitxor(self, rhs: BTreeSet<T, A>) -> BTreeSet<T, A> {
1622+
// Iterate through the smaller set
1623+
let [mut a, mut b] = minmax_by_key(self, rhs, BTreeSet::len);
1624+
1625+
// This is essentially
1626+
// a = a - b (retain elements that are *not* in b)
1627+
// b = b - a (remove all elements that are in a)
1628+
a.retain(|e| !b.remove(e));
1629+
1630+
// Union of the differences
1631+
a | b
1632+
}
1633+
}
1634+
15731635
#[stable(feature = "rust1", since = "1.0.0")]
15741636
impl<T: Ord + Clone, A: Allocator + Clone> BitAnd<&BTreeSet<T, A>> for &BTreeSet<T, A> {
15751637
type Output = BTreeSet<T, A>;
@@ -1595,6 +1657,29 @@ impl<T: Ord + Clone, A: Allocator + Clone> BitAnd<&BTreeSet<T, A>> for &BTreeSet
15951657
}
15961658
}
15971659

1660+
#[stable(feature = "set_owned_ops", since = "CURRENT_RUSTC_VERSION")]
1661+
impl<T: Ord, A: Allocator + Clone> BitAnd<&BTreeSet<T, A>> for BTreeSet<T, A> {
1662+
type Output = BTreeSet<T, A>;
1663+
1664+
/// Returns the intersection of `self` and `rhs` as a new `BTreeSet<T>`.
1665+
///
1666+
/// # Examples
1667+
///
1668+
/// ```
1669+
/// use std::collections::BTreeSet;
1670+
///
1671+
/// let a = BTreeSet::from([1, 2, 3]);
1672+
/// let b = BTreeSet::from([2, 3, 4]);
1673+
///
1674+
/// let result = a & &b;
1675+
/// assert_eq!(result, BTreeSet::from([2, 3]));
1676+
/// ```
1677+
fn bitand(mut self, rhs: &BTreeSet<T, A>) -> BTreeSet<T, A> {
1678+
self.retain(|e| rhs.contains(e));
1679+
self
1680+
}
1681+
}
1682+
15981683
#[stable(feature = "rust1", since = "1.0.0")]
15991684
impl<T: Ord + Clone, A: Allocator + Clone> BitOr<&BTreeSet<T, A>> for &BTreeSet<T, A> {
16001685
type Output = BTreeSet<T, A>;
@@ -1620,6 +1705,33 @@ impl<T: Ord + Clone, A: Allocator + Clone> BitOr<&BTreeSet<T, A>> for &BTreeSet<
16201705
}
16211706
}
16221707

1708+
#[stable(feature = "set_owned_ops", since = "CURRENT_RUSTC_VERSION")]
1709+
impl<T: Ord, A: Allocator + Clone> BitOr<BTreeSet<T, A>> for BTreeSet<T, A> {
1710+
type Output = BTreeSet<T, A>;
1711+
1712+
/// Returns the union of `self` and `rhs` as a new `BTreeSet<T>`.
1713+
///
1714+
/// # Examples
1715+
///
1716+
/// ```
1717+
/// use std::collections::BTreeSet;
1718+
///
1719+
/// let a = BTreeSet::from([1, 2, 3]);
1720+
/// let b = BTreeSet::from([3, 4, 5]);
1721+
///
1722+
/// let result = a | b;
1723+
/// assert_eq!(result, BTreeSet::from([1, 2, 3, 4, 5]));
1724+
/// ```
1725+
fn bitor(self, rhs: BTreeSet<T, A>) -> BTreeSet<T, A> {
1726+
// Try to avoid unnecessary moves, by keeping set with the bigger length
1727+
let [a, mut b] = minmax_by_key(self, rhs, BTreeSet::len);
1728+
1729+
b.extend(a);
1730+
1731+
b
1732+
}
1733+
}
1734+
16231735
#[stable(feature = "rust1", since = "1.0.0")]
16241736
impl<T: Debug, A: Allocator + Clone> Debug for BTreeSet<T, A> {
16251737
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -2397,5 +2509,9 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> {
23972509
#[unstable(feature = "btree_cursors", issue = "107540")]
23982510
pub use super::map::UnorderedKeyError;
23992511

2512+
fn minmax_by_key<T, K: Ord>(a: T, b: T, k: impl Fn(&T) -> K) -> [T; 2] {
2513+
if k(&a) <= k(&b) { [a, b] } else { [b, a] }
2514+
}
2515+
24002516
#[cfg(test)]
24012517
mod tests;

0 commit comments

Comments
 (0)