diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 17e937c5af257..31cad0fdbb1a7 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -1796,6 +1796,89 @@ impl BitSet { self.other_op(other, |w1, w2| w1 ^ w2); } + /// Moves all elements from `other` into `Self`, leaving `other` empty. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections, bit_set_append_split_off)] + /// use std::collections::{BitVec, BitSet}; + /// + /// let mut a = BitSet::new(); + /// a.insert(2); + /// a.insert(6); + /// + /// let mut b = BitSet::new(); + /// b.insert(1); + /// b.insert(3); + /// b.insert(6); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.len(), 4); + /// assert_eq!(b.len(), 0); + /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010]))); + /// ``` + #[unstable(feature = "bit_set_append_split_off", + reason = "recently added as part of collections reform 2")] + pub fn append(&mut self, other: &mut Self) { + self.union_with(other); + other.clear(); + } + + /// Splits the `BitSet` into two at the given key including the key. + /// Retains the first part in-place while returning the second part. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections, bit_set_append_split_off)] + /// use std::collections::{BitSet, BitVec}; + /// let mut a = BitSet::new(); + /// a.insert(2); + /// a.insert(6); + /// a.insert(1); + /// a.insert(3); + /// + /// let b = a.split_off(3); + /// + /// assert_eq!(a.len(), 2); + /// assert_eq!(b.len(), 2); + /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100000]))); + /// assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b00010010]))); + /// ``` + #[unstable(feature = "bit_set_append_split_off", + reason = "recently added as part of collections reform 2")] + pub fn split_off(&mut self, at: usize) -> Self { + let mut other = BitSet::new(); + + if at == 0 { + swap(self, &mut other); + return other; + } else if at >= self.bit_vec.len() { + return other; + } + + // Calculate block and bit at which to split + let w = at / u32::BITS; + let b = at % u32::BITS; + + // Pad `other` with `w` zero blocks, + // append `self`'s blocks in the range from `w` to the end to `other` + other.bit_vec.storage.extend(repeat(0u32).take(w) + .chain(self.bit_vec.storage[w..].iter().cloned())); + other.bit_vec.nbits = self.bit_vec.nbits; + + if b > 0 { + other.bit_vec.storage[w] &= !0 << b; + } + + // Sets `bit_vec.len()` and fixes the last block as well + self.bit_vec.truncate(at); + + other + } + /// Returns the number of set bits in this set. #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcollectionstest/bit/set.rs b/src/libcollectionstest/bit/set.rs index d020f551dd55d..e6aa15608f03e 100644 --- a/src/libcollectionstest/bit/set.rs +++ b/src/libcollectionstest/bit/set.rs @@ -387,6 +387,67 @@ fn test_bit_vec_clone() { assert!(b.contains(&1000)); } +#[test] +fn test_bit_set_append() { + let mut a = BitSet::new(); + a.insert(2); + a.insert(6); + + let mut b = BitSet::new(); + b.insert(1); + b.insert(3); + b.insert(6); + + a.append(&mut b); + + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 0); + assert!(b.capacity() >= 6); + + assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010]))); +} + +#[test] +fn test_bit_set_split_off() { + // Split at 0 + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101])); + + let b = a.split_off(0); + + assert_eq!(a.len(), 0); + assert_eq!(b.len(), 21); + + assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101]))); + + // Split behind last element + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101])); + + let b = a.split_off(50); + + assert_eq!(a.len(), 21); + assert_eq!(b.len(), 0); + + assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101]))); + + // Split at arbitrary element + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01101011, 0b10101101])); + + let b = a.split_off(34); + + assert_eq!(a.len(), 12); + assert_eq!(b.len(), 9); + + assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, + 0b00110011, 0b01000000]))); + assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0, 0, 0, 0, + 0b00101011, 0b10101101]))); +} + mod bench { use std::collections::{BitSet, BitVec}; use std::__rand::{Rng, thread_rng, ThreadRng}; diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 154bdd56c5a68..9b50478472fa9 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(bit_set_append_split_off)] #![feature(bit_vec_append_split_off)] #![feature(box_syntax)] #![feature(collections)]