Auto merge of #24890 - jooert:bitvec-append-split_off, r=alexcrichton

cc #19986 

r? @Gankro
This commit is contained in:
bors 2015-05-07 00:20:25 +00:00
commit e8b4c84e39
3 changed files with 237 additions and 0 deletions

View File

@ -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};
@ -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

View File

@ -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;

View File

@ -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)]