Skip to content

Commit

Permalink
Auto merge of #24890 - jooert:bitvec-append-split_off, r=alexcrichton
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed May 7, 2015
2 parents 8767e97 + d55a7e8 commit e8b4c84
Show file tree
Hide file tree
Showing 3 changed files with 237 additions and 0 deletions.
101 changes: 101 additions & 0 deletions src/libcollections/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ use core::hash;
use core::iter::RandomAccessIterator;
use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned};
use core::iter::{self, FromIterator};
use core::mem::swap;
use core::ops::Index;
use core::slice;
use core::{u8, u32, usize};
Expand Down Expand Up @@ -602,6 +603,106 @@ impl BitVec {
Iter { bit_vec: self, next_idx: 0, end_idx: self.nbits }
}

/// Moves all bits from `other` into `Self`, leaving `other` empty.
///
/// # Examples
///
/// ```
/// # #![feature(collections, bit_vec_append_split_off)]
/// use std::collections::BitVec;
///
/// let mut a = BitVec::from_bytes(&[0b10000000]);
/// let mut b = BitVec::from_bytes(&[0b01100001]);
///
/// a.append(&mut b);
///
/// assert_eq!(a.len(), 16);
/// assert_eq!(b.len(), 0);
/// assert!(a.eq_vec(&[true, false, false, false, false, false, false, false,
/// false, true, true, false, false, false, false, true]));
/// ```
#[unstable(feature = "bit_vec_append_split_off",
reason = "recently added as part of collections reform 2")]
pub fn append(&mut self, other: &mut Self) {
let b = self.len() % u32::BITS;

self.nbits += other.len();
other.nbits = 0;

if b == 0 {
self.storage.append(&mut other.storage);
} else {
self.storage.reserve(other.storage.len());

for block in other.storage.drain(..) {
*(self.storage.last_mut().unwrap()) |= block << b;
self.storage.push(block >> (u32::BITS - b));
}
}
}

/// Splits the `BitVec` into two at the given bit,
/// retaining the first half in-place and returning the second one.
///
/// # Examples
///
/// ```
/// # #![feature(collections, bit_vec_append_split_off)]
/// use std::collections::BitVec;
/// let mut a = BitVec::new();
/// a.push(true);
/// a.push(false);
/// a.push(false);
/// a.push(true);
///
/// let b = a.split_off(2);
///
/// assert_eq!(a.len(), 2);
/// assert_eq!(b.len(), 2);
/// assert!(a.eq_vec(&[true, false]));
/// assert!(b.eq_vec(&[false, true]));
/// ```
#[unstable(feature = "bit_vec_append_split_off",
reason = "recently added as part of collections reform 2")]
pub fn split_off(&mut self, at: usize) -> Self {
assert!(at <= self.len(), "`at` out of bounds");

let mut other = BitVec::new();

if at == 0 {
swap(self, &mut other);
return other;
} else if at == self.len() {
return other;
}

let w = at / u32::BITS;
let b = at % u32::BITS;
other.nbits = self.nbits - at;
self.nbits = at;
if b == 0 {
// Split at block boundary
other.storage = self.storage.split_off(w);
} else {
other.storage.reserve(self.storage.len() - w);

{
let mut iter = self.storage[w..].iter();
let mut last = *iter.next().unwrap();
for &cur in iter {
other.storage.push((last >> b) | (cur << (u32::BITS - b)));
last = cur;
}
other.storage.push(last >> b);
}

self.storage.truncate(w+1);
self.fix_last_block();
}

other
}

/// Returns `true` if all bits are 0.
///
/// # Examples
Expand Down
135 changes: 135 additions & 0 deletions src/libcollectionstest/bit/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,141 @@ fn test_bit_vec_extend() {
0b01001001, 0b10010010, 0b10111101]));
}

#[test]
fn test_bit_vec_append() {
// Append to BitVec that holds a multiple of u32::BITS bits
let mut a = BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, 0b00110011]);
let mut b = BitVec::new();
b.push(false);
b.push(true);
b.push(true);

a.append(&mut b);

assert_eq!(a.len(), 35);
assert_eq!(b.len(), 0);
assert!(b.capacity() >= 3);

assert!(a.eq_vec(&[true, false, true, false, false, false, false, false,
false, false, false, true, false, false, true, false,
true, false, false, true, false, false, true, false,
false, false, true, true, false, false, true, true,
false, true, true]));

// Append to arbitrary BitVec
let mut a = BitVec::new();
a.push(true);
a.push(false);

let mut b = BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, 0b00110011, 0b10010101]);

a.append(&mut b);

assert_eq!(a.len(), 42);
assert_eq!(b.len(), 0);
assert!(b.capacity() >= 40);

assert!(a.eq_vec(&[true, false, true, false, true, false, false, false,
false, false, false, false, false, true, false, false,
true, false, true, false, false, true, false, false,
true, false, false, false, true, true, false, false,
true, true, true, false, false, true, false, true,
false, true]));

// Append to empty BitVec
let mut a = BitVec::new();
let mut b = BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, 0b00110011, 0b10010101]);

a.append(&mut b);

assert_eq!(a.len(), 40);
assert_eq!(b.len(), 0);
assert!(b.capacity() >= 40);

assert!(a.eq_vec(&[true, false, true, false, false, false, false, false,
false, false, false, true, false, false, true, false,
true, false, false, true, false, false, true, false,
false, false, true, true, false, false, true, true,
true, false, false, true, false, true, false, true]));

// Append empty BitVec
let mut a = BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, 0b00110011, 0b10010101]);
let mut b = BitVec::new();

a.append(&mut b);

assert_eq!(a.len(), 40);
assert_eq!(b.len(), 0);

assert!(a.eq_vec(&[true, false, true, false, false, false, false, false,
false, false, false, true, false, false, true, false,
true, false, false, true, false, false, true, false,
false, false, true, true, false, false, true, true,
true, false, false, true, false, true, false, true]));
}

#[test]
fn test_bit_vec_split_off() {
// Split at 0
let mut a = BitVec::new();
a.push(true);
a.push(false);
a.push(false);
a.push(true);

let b = a.split_off(0);

assert_eq!(a.len(), 0);
assert_eq!(b.len(), 4);

assert!(b.eq_vec(&[true, false, false, true]));

// Split at last bit
a.truncate(0);
a.push(true);
a.push(false);
a.push(false);
a.push(true);

let b = a.split_off(4);

assert_eq!(a.len(), 4);
assert_eq!(b.len(), 0);

assert!(a.eq_vec(&[true, false, false, true]));

// Split at block boundary
let mut a = BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, 0b00110011, 0b11110011]);

let b = a.split_off(32);

assert_eq!(a.len(), 32);
assert_eq!(b.len(), 8);

assert!(a.eq_vec(&[true, false, true, false, false, false, false, false,
false, false, false, true, false, false, true, false,
true, false, false, true, false, false, true, false,
false, false, true, true, false, false, true, true]));
assert!(b.eq_vec(&[true, true, true, true, false, false, true, true]));

// Don't split at block boundary
let mut a = BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010, 0b00110011,
0b01101011, 0b10101101]);

let b = a.split_off(13);

assert_eq!(a.len(), 13);
assert_eq!(b.len(), 35);

assert!(a.eq_vec(&[true, false, true, false, false, false, false, false,
false, false, false, true, false]));
assert!(b.eq_vec(&[false, true, false, true, false, false, true, false,
false, true, false, false, false, true, true, false,
false, true, true, false, true, true, false, true,
false, true, true, true, false, true, false, true,
true, false, true]));
}

mod bench {
use std::collections::BitVec;
use std::u32;
Expand Down
1 change: 1 addition & 0 deletions src/libcollectionstest/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(bit_vec_append_split_off)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(collections_drain)]
Expand Down

0 comments on commit e8b4c84

Please sign in to comment.