bigwise 0.4.0

Bitwise operations on fixed-size, arbitrary big buffer of bytes.
Documentation
use Bigwise;
use BwPair;
use Bw64;
use Bw128;
use Bw256;
use Bw32k;
use quickcheck::{Arbitrary, Gen, quickcheck, TestResult};

impl Arbitrary for Bw64 {
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        g.gen()
    }
}

impl <T> Arbitrary for BwPair<T> where T: Bigwise + Send + 'static + Clone
{
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        g.gen()
    }
}

fn generic_empty<T: Bigwise>() {
    let x = T::empty();
    for i in 0..T::size() {
        assert!(x.get(i) == false);
    }
}

#[test] fn bw64_empty() { generic_empty::<Bw64>(); }
#[test] fn bw128_empty() { generic_empty::<Bw128>(); }
#[test] fn bw256_empty() { generic_empty::<Bw256>(); }
#[test] fn bw32k_empty() { generic_empty::<Bw32k>(); }

fn generic_full<T: Bigwise>() {
    let x = T::full();
    for i in 0..T::size() {
        assert!(x.get(i) == true);
    }
}

#[test] fn bw64_full() { generic_full::<Bw64>(); }
#[test] fn bw128_full() { generic_full::<Bw128>(); }
#[test] fn bw256_full() { generic_full::<Bw256>(); }
#[test] fn bw32k_full() { generic_full::<Bw32k>(); }

fn generic_set_get<T: Bigwise>() {
    for i in 0..T::size() {
        let mut x = T::empty();
        assert!(x.get(i) == false);
        x.set(i, true);
        assert!(x.get(i) == true);
        x.set(i, false);
        assert!(x.get(i) == false);
    }
}

#[test] fn bw64_set_get() { generic_set_get::<Bw64>(); }
#[test] fn bw128_set_get() { generic_set_get::<Bw128>(); }
#[test] fn bw256_set_get() { generic_set_get::<Bw256>(); }
#[test] fn bw32k_set_get() { generic_set_get::<Bw32k>(); }

fn prop_to_bytes_from_bytes<T: Bigwise>(x: T) -> bool {
    x == T::from_bytes(&x.to_bytes())
}

#[test] fn bw64_to_bytes_from_bytes() { quickcheck(prop_to_bytes_from_bytes::<Bw64> as fn(Bw64) -> bool); }
#[test] fn bw128_to_bytes_from_bytes() { quickcheck(prop_to_bytes_from_bytes::<Bw128> as fn(Bw128) -> bool); }
#[test] fn bw256_to_bytes_from_bytes() { quickcheck(prop_to_bytes_from_bytes::<Bw256> as fn(Bw256) -> bool); }
#[test] fn bw32k_to_bytes_from_bytes() { quickcheck(prop_to_bytes_from_bytes::<Bw32k> as fn(Bw32k) -> bool); }

fn generic_from_empty_bytes<T: Bigwise>() {
    assert!(T::from_bytes(&[]) == T::empty());
}

#[test] fn bw64_from_empty_bytes() { generic_from_empty_bytes::<Bw64>(); }
#[test] fn bw128_from_empty_bytes() { generic_from_empty_bytes::<Bw128>(); }
#[test] fn bw256_from_empty_bytes() { generic_from_empty_bytes::<Bw256>(); }
#[test] fn bw32k_from_empty_bytes() { generic_from_empty_bytes::<Bw32k>(); }

fn generic_from_one_byte<T: Bigwise>() {
    let len = (T::size() / 8) as usize;
    let x = T::from_bytes(&[0xFF]).to_bytes();
    assert!(x.len() == len);
    assert!(x.iter().take(len-1).all(|&v| v == 0));
    assert!(x.last() == Some(&0xFF));
}

#[test] fn bw64_from_one_byte() { generic_from_one_byte::<Bw64>(); }
#[test] fn bw128_from_one_byte() { generic_from_one_byte::<Bw128>(); }
#[test] fn bw256_from_one_byte() { generic_from_one_byte::<Bw256>(); }
#[test] fn bw32k_from_one_byte() { generic_from_one_byte::<Bw32k>(); }

fn generic_iter_empty<T: Bigwise>() {
    use std::iter::repeat;
    let v1 : Vec<_> = T::empty().into_iter().collect();
    let v2 : Vec<_> = repeat(false).take(T::size() as usize).collect();
    assert!(v1 == v2);
    assert!(v1.len() == T::size() as usize);
}

#[test] fn bw64_iter_empty() { generic_iter_empty::<Bw64>(); }
#[test] fn bw128_iter_empty() { generic_iter_empty::<Bw128>(); }
#[test] fn bw256_iter_empty() { generic_iter_empty::<Bw256>(); }
#[test] fn bw32k_iter_empty() { generic_iter_empty::<Bw32k>(); }

fn generic_iter_full<T: Bigwise>() {
    use std::iter::repeat;
    let v1 : Vec<_> = T::full().into_iter().collect();
    let v2 : Vec<_> = repeat(true).take(T::size() as usize).collect();
    assert!(v1 == v2);
    assert!(v1.len() == T::size() as usize);
}

#[test] fn bw64_iter_full() { generic_iter_full::<Bw64>(); }
#[test] fn bw128_iter_full() { generic_iter_full::<Bw128>(); }
#[test] fn bw256_iter_full() { generic_iter_full::<Bw256>(); }
#[test] fn bw32k_iter_full() { generic_iter_full::<Bw32k>(); }

fn prop_iter_get<T: Bigwise>(x: T) -> bool {
    x.into_iter().enumerate().all(|(i, b)| x.get(i as u32) == b)
}

#[test] fn bw64_iter_get() { quickcheck(prop_iter_get::<Bw64> as fn(Bw64) -> bool); }
#[test] fn bw128_iter_get() { quickcheck(prop_iter_get::<Bw128> as fn(Bw128) -> bool); }
#[test] fn bw256_iter_get() { quickcheck(prop_iter_get::<Bw256> as fn(Bw256) -> bool); }
#[test] fn bw32k_iter_get() { quickcheck(prop_iter_get::<Bw32k> as fn(Bw32k) -> bool); }

fn prop_shift_left<T: Bigwise>((original, n) : (T, u32)) -> TestResult {
    if n >= T::size() {
        return TestResult::discard();
    }
    let shifted = original << n;
    let v_original : Vec<_> = original.into_iter().take((T::size()-n) as usize).collect();
    let v_shifted : Vec<_> = shifted.into_iter().skip(n as usize).collect();
    TestResult::from_bool(v_original == v_shifted)
}

#[test] fn bw64_shift_left() { quickcheck(prop_shift_left::<Bw64> as fn((Bw64, u32)) -> TestResult); }
#[test] fn bw128_shift_left() { quickcheck(prop_shift_left::<Bw128> as fn((Bw128, u32)) -> TestResult); }
#[test] fn bw256_shift_left() { quickcheck(prop_shift_left::<Bw256> as fn((Bw256, u32)) -> TestResult); }
#[test] fn bw32k_shift_left() { quickcheck(prop_shift_left::<Bw32k> as fn((Bw32k, u32)) -> TestResult); }

fn prop_shift_right<T: Bigwise>((original, n) : (T, u32)) -> TestResult {
    if n >= T::size() {
        return TestResult::discard();
    }
    let shifted = original >> n;
    let v_original : Vec<_> = original.into_iter().skip(n as usize).collect();
    let v_shifted : Vec<_> = shifted.into_iter().take((T::size()-n) as usize).collect();
    TestResult::from_bool(v_original == v_shifted)
}

#[test] fn bw64_shift_right() { quickcheck(prop_shift_right::<Bw64> as fn((Bw64, u32)) -> TestResult); }
#[test] fn bw128_shift_right() { quickcheck(prop_shift_right::<Bw128> as fn((Bw128, u32)) -> TestResult); }
#[test] fn bw256_shift_right() { quickcheck(prop_shift_right::<Bw256> as fn((Bw256, u32)) -> TestResult); }
#[test] fn bw32k_shift_right() { quickcheck(prop_shift_right::<Bw32k> as fn((Bw32k, u32)) -> TestResult); }

fn prop_and<T: Bigwise>(xx: (T, T)) -> bool {
    let res = xx.0 & xx.1;
    xx.0.into_iter().zip(xx.1.into_iter())
        .map(|(x1,x2)| x1 & x2)
        .zip(res.into_iter())
        .all(|(expected, observed)| expected == observed)
}

#[test] fn bw64_and() { quickcheck(prop_and::<Bw64> as fn((Bw64, Bw64)) -> bool); }
#[test] fn bw128_and() { quickcheck(prop_and::<Bw128> as fn((Bw128, Bw128)) -> bool); }
#[test] fn bw256_and() { quickcheck(prop_and::<Bw256> as fn((Bw256, Bw256)) -> bool); }
#[test] fn bw32k_and() { quickcheck(prop_and::<Bw32k> as fn((Bw32k, Bw32k)) -> bool); }

fn prop_or<T: Bigwise>(xx: (T, T)) -> bool {
    let res = xx.0 | xx.1;
    xx.0.into_iter().zip(xx.1.into_iter())
        .map(|(x1,x2)| x1 | x2)
        .zip(res.into_iter())
        .all(|(expected, observed)| expected == observed)
}

#[test] fn bw64_or() { quickcheck(prop_or::<Bw64> as fn((Bw64, Bw64)) -> bool); }
#[test] fn bw128_or() { quickcheck(prop_or::<Bw128> as fn((Bw128, Bw128)) -> bool); }
#[test] fn bw256_or() { quickcheck(prop_or::<Bw256> as fn((Bw256, Bw256)) -> bool); }
#[test] fn bw32k_or() { quickcheck(prop_or::<Bw32k> as fn((Bw32k, Bw32k)) -> bool); }

fn prop_xor<T: Bigwise>(xx: (T, T)) -> bool {
    let res = xx.0 ^ xx.1;
    xx.0.into_iter().zip(xx.1.into_iter())
        .map(|(x1,x2)| x1 ^ x2)
        .zip(res.into_iter())
        .all(|(expected, observed)| expected == observed)
}

#[test] fn bw64_xor() { quickcheck(prop_xor::<Bw64> as fn((Bw64, Bw64)) -> bool); }
#[test] fn bw128_xor() { quickcheck(prop_xor::<Bw128> as fn((Bw128, Bw128)) -> bool); }
#[test] fn bw256_xor() { quickcheck(prop_xor::<Bw256> as fn((Bw256, Bw256)) -> bool); }
#[test] fn bw32k_xor() { quickcheck(prop_xor::<Bw32k> as fn((Bw32k, Bw32k)) -> bool); }

fn prop_not<T: Bigwise>(x: T) -> bool {
    let res = !x;
    x.into_iter().zip(res.into_iter())
        .all(|(before, after)| before != after)
}

#[test] fn bw64_not() { quickcheck(prop_not::<Bw64> as fn(Bw64) -> bool); }
#[test] fn bw128_not() { quickcheck(prop_not::<Bw128> as fn(Bw128) -> bool); }
#[test] fn bw256_not() { quickcheck(prop_not::<Bw256> as fn(Bw256) -> bool); }
#[test] fn bw32k_not() { quickcheck(prop_not::<Bw32k> as fn(Bw32k) -> bool); }

fn prop_rotate_right<T: Bigwise>((original, n) : (T, u32)) -> TestResult {
    if n >= T::size() {
        return TestResult::discard();
    }
    let rotated = original.rotate_right(n);
    let n = n as usize;
    let mut v_original = vec!();
    v_original.extend(original.into_iter().skip(n));
    v_original.extend(original.into_iter().take(n));
    let v_rotated : Vec<_> = rotated.into_iter().collect();
    TestResult::from_bool(v_original == v_rotated)
}

#[test] fn bw64_rotate_right() { quickcheck(prop_rotate_right::<Bw64> as fn((Bw64, u32)) -> TestResult); }
#[test] fn bw128_rotate_right() { quickcheck(prop_rotate_right::<Bw128> as fn((Bw128, u32)) -> TestResult); }
#[test] fn bw256_rotate_right() { quickcheck(prop_rotate_right::<Bw256> as fn((Bw256, u32)) -> TestResult); }
#[test] fn bw32k_rotate_right() { quickcheck(prop_rotate_right::<Bw32k> as fn((Bw32k, u32)) -> TestResult); }

fn prop_rotate_left<T: Bigwise>((original, n) : (T, u32)) -> TestResult {
    if n >= T::size() {
        return TestResult::discard();
    }
    let rotated = original.rotate_left(n);
    let p = (T::size() - n) as usize;
    let mut v_original = vec!();
    v_original.extend(original.into_iter().skip(p));
    v_original.extend(original.into_iter().take(p));
    let v_rotated : Vec<_> = rotated.into_iter().collect();
    TestResult::from_bool(v_original == v_rotated)
}

#[test] fn bw64_rotate_left() { quickcheck(prop_rotate_left::<Bw64> as fn((Bw64, u32)) -> TestResult); }
#[test] fn bw128_rotate_left() { quickcheck(prop_rotate_left::<Bw128> as fn((Bw128, u32)) -> TestResult); }
#[test] fn bw256_rotate_left() { quickcheck(prop_rotate_left::<Bw256> as fn((Bw256, u32)) -> TestResult); }
#[test] fn bw32k_rotate_left() { quickcheck(prop_rotate_left::<Bw32k> as fn((Bw32k, u32)) -> TestResult); }