Add progress on bitfields

This commit is contained in:
Paul Hauner 2019-07-08 11:54:47 +10:00
parent ecb0bf11c7
commit 636ebb0d4e
No known key found for this signature in database
GPG Key ID: 5E2CFF9B75FA63DF
3 changed files with 357 additions and 10 deletions

View File

@ -75,6 +75,16 @@ impl<N: Unsigned> BitList<N> {
pub fn max_len() -> usize { pub fn max_len() -> usize {
N::to_usize() N::to_usize()
} }
/// Create a new bitfield using the supplied `bytes` as input
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
Self::validate_length(bytes.len().saturating_mul(8))?;
Ok(Self {
bitfield: Bitfield::from_bytes(&reverse_bit_order(bytes.to_vec())),
_phantom: PhantomData,
})
}
} }
impl<N: Unsigned + Clone> BitList<N> { impl<N: Unsigned + Clone> BitList<N> {
@ -153,7 +163,7 @@ impl<N: Unsigned> default::Default for BitList<N> {
} }
#[cfg(test)] #[cfg(test)]
mod test_bitlist { mod test {
use super::*; use super::*;
use serde_yaml; use serde_yaml;
use ssz::ssz_encode; use ssz::ssz_encode;

View File

@ -54,6 +54,18 @@ impl<N: Unsigned> BitVector<N> {
N::to_usize() N::to_usize()
} }
/// Create a new bitfield using the supplied `bytes` as input
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
if Self::capacity() >= 8 && bytes.len() != 1 {
Self::validate_length(bytes.len().saturating_mul(8))?;
}
Ok(Self {
bitfield: Bitfield::from_bytes(&reverse_bit_order(bytes.to_vec())),
_phantom: PhantomData,
})
}
fn validate_length(len: usize) -> Result<(), Error> { fn validate_length(len: usize) -> Result<(), Error> {
let fixed_len = N::to_usize(); let fixed_len = N::to_usize();
@ -67,3 +79,266 @@ impl<N: Unsigned> BitVector<N> {
} }
} }
} }
#[cfg(test)]
mod test {
use super::*;
use serde_yaml;
use ssz::ssz_encode;
// use tree_hash::TreeHash;
pub type BitVector4 = BitVector<typenum::U4>;
pub type BitVector1024 = BitVector<typenum::U1024>;
/*
#[test]
pub fn cached_tree_hash() {
let original = BitVector1024::from_bytes(&vec![18; 12][..]);
let mut cache = cached_tree_hash::TreeHashCache::new(&original).unwrap();
assert_eq!(
cache.tree_hash_root().unwrap().to_vec(),
original.tree_hash_root()
);
let modified = BitVector1024::from_bytes(&vec![2; 1][..]);
cache.update(&modified).unwrap();
assert_eq!(
cache.tree_hash_root().unwrap().to_vec(),
modified.tree_hash_root()
);
}
*/
#[test]
fn new_bitfield() {
let mut field = BitVector1024::new();
let original_len = field.len();
assert_eq!(original_len, 1024);
for i in 0..1028 {
if i < original_len {
assert!(!field.get(i).unwrap());
assert!(field.set(i, true).is_ok());
} else {
assert!(field.get(i).is_err());
assert!(field.set(i, true).is_err());
}
}
}
#[test]
fn from_bytes_bitvec4() {
let bytes = &[3];
let bitvec = BitVector4::from_bytes(bytes).unwrap();
assert_eq!(bitvec.get(0), Ok(true));
assert_eq!(bitvec.get(1), Ok(true));
assert_eq!(bitvec.get(2), Ok(false));
assert_eq!(bitvec.get(3), Ok(false));
assert!(bitvec.get(4).is_err());
}
/*
#[test]
fn from_bytes_bytes_too_long() {
let bytes = &[0, 0];
assert_eq!(
BitVector4::from_bytes(bytes),
Err(Error::InvalidLength { i: 16, len: 4 })
);
}
const INPUT: &[u8] = &[0b0100_0000, 0b0100_0000];
#[test]
fn get_from_bitfield() {
let field = BitVector1024::from_bytes(INPUT).unwrap();
field.get(0).unwrap();
field.get(6).unwrap();
field.get(14).unwrap();
}
#[test]
fn set_for_bitfield() {
let mut field = BitVector1024::from_bytes(INPUT).unwrap();
field.set(10, true).unwrap();
field.get(10).unwrap();
field.set(6, false).unwrap();
field.get(6).unwrap();
}
#[test]
fn len() {
let field = BitVector1024::from_bytes(INPUT).unwrap();
assert_eq!(field.len(), 16);
let field = BitVector1024::new();
assert_eq!(field.len(), 0);
}
#[test]
fn num_set_bits() {
let field = BitVector1024::from_bytes(INPUT).unwrap();
assert_eq!(field.num_set_bits(), 2);
let field = BitVector1024::new();
assert_eq!(field.num_set_bits(), 0);
}
#[test]
fn to_bytes() {
let field = BitVector1024::from_bytes(INPUT).unwrap();
assert_eq!(field.to_bytes(), INPUT);
let field = BitVector1024::new();
assert_eq!(field.to_bytes(), vec![0]);
}
#[test]
fn out_of_bounds() {
let mut field = BitVector1024::from_bytes(INPUT).unwrap();
let out_of_bounds_index = field.len();
assert!(field.set(out_of_bounds_index, true).is_ok());
assert!(field.len() == out_of_bounds_index + 1);
assert!(field.get(out_of_bounds_index).unwrap());
for i in 0..100 {
if i <= out_of_bounds_index {
assert!(field.set(i, true).is_ok());
} else {
assert!(field.set(i, true).is_ok());
}
}
}
#[test]
fn grows_with_false() {
let input_all_set: &[u8] = &[0b1111_1111, 0b1111_1111];
let mut field = BitVector1024::from_bytes(input_all_set).unwrap();
// Define `a` and `b`, where both are out of bounds and `b` is greater than `a`.
let a = field.len();
let b = a + 1;
// Ensure `a` is out-of-bounds for test integrity.
assert!(field.get(a).is_err());
// Set `b` to `true`..
assert!(field.set(b, true).is_ok());
// Ensure that `a` wasn't also set to `true` during the grow.
assert_eq!(field.get(a), Ok(false));
assert_eq!(field.get(b), Ok(true));
}
#[test]
fn num_bytes() {
let field = BitVector1024::from_bytes(INPUT).unwrap();
assert_eq!(field.num_bytes(), 2);
let field = BitVector1024::from_elem(2, true).unwrap();
assert_eq!(field.num_bytes(), 1);
let field = BitVector1024::from_elem(13, true).unwrap();
assert_eq!(field.num_bytes(), 2);
}
#[test]
fn ssz_encoding() {
let field = create_bitfield();
assert_eq!(field.as_ssz_bytes(), vec![0b0000_0011, 0b1000_0111]);
let field = BitVector1024::from_elem(18, true).unwrap();
assert_eq!(
field.as_ssz_bytes(),
vec![0b0000_0011, 0b1111_1111, 0b1111_1111]
);
let mut b = BitVector1024::new();
b.set(1, true).unwrap();
assert_eq!(ssz_encode(&b), vec![0b0000_0010]);
}
fn create_bitfield() -> BitVector1024 {
let count = 2 * 8;
let mut field = BitVector1024::with_capacity(count).unwrap();
let indices = &[0, 1, 2, 7, 8, 9];
for &i in indices {
field.set(i, true).unwrap();
}
field
}
#[test]
fn ssz_decode() {
let encoded = vec![0b0000_0011, 0b1000_0111];
let field = BitVector1024::from_ssz_bytes(&encoded).unwrap();
let expected = create_bitfield();
assert_eq!(field, expected);
let encoded = vec![255, 255, 3];
let field = BitVector1024::from_ssz_bytes(&encoded).unwrap();
let expected = BitVector1024::from_bytes(&[255, 255, 3]).unwrap();
assert_eq!(field, expected);
}
#[test]
fn serialize_deserialize() {
use serde_yaml::Value;
let data: &[(_, &[_])] = &[
("0x01", &[0b00000001]),
("0xf301", &[0b11110011, 0b00000001]),
];
for (hex_data, bytes) in data {
let bitfield = BitVector1024::from_bytes(bytes).unwrap();
assert_eq!(
serde_yaml::from_str::<BitVector1024>(hex_data).unwrap(),
bitfield
);
assert_eq!(
serde_yaml::to_value(&bitfield).unwrap(),
Value::String(hex_data.to_string())
);
}
}
#[test]
fn ssz_round_trip() {
let original = BitVector1024::from_bytes(&vec![18; 12][..]).unwrap();
let ssz = ssz_encode(&original);
let decoded = BitVector1024::from_ssz_bytes(&ssz).unwrap();
assert_eq!(original, decoded);
}
#[test]
fn bitor() {
let a = BitVector1024::from_bytes(&vec![2, 8, 1][..]).unwrap();
let b = BitVector1024::from_bytes(&vec![4, 8, 16][..]).unwrap();
let c = BitVector1024::from_bytes(&vec![6, 8, 17][..]).unwrap();
assert_eq!(c, a | b);
}
#[test]
fn is_zero() {
let yes_data: &[&[u8]] = &[&[], &[0], &[0, 0], &[0, 0, 0]];
for bytes in yes_data {
assert!(BitVector1024::from_bytes(bytes).unwrap().is_zero());
}
let no_data: &[&[u8]] = &[&[1], &[6], &[0, 1], &[0, 0, 1], &[0, 0, 255]];
for bytes in no_data {
assert!(!BitVector1024::from_bytes(bytes).unwrap().is_zero());
}
}
*/
}

View File

@ -34,15 +34,6 @@ macro_rules! impl_bitfield_fns {
}) })
} }
/// Create a new bitfield using the supplied `bytes` as input
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
Self::validate_length(bytes.len().saturating_mul(8))?;
Ok(Self {
bitfield: Bitfield::from_bytes(&reverse_bit_order(bytes.to_vec())),
_phantom: PhantomData,
})
}
/// Returns a vector of bytes representing the bitfield /// Returns a vector of bytes representing the bitfield
pub fn to_bytes(&self) -> Vec<u8> { pub fn to_bytes(&self) -> Vec<u8> {
if self.bitfield.is_empty() { if self.bitfield.is_empty() {
@ -227,3 +218,74 @@ pub fn reverse_bit_order(mut bytes: Vec<u8>) -> Vec<u8> {
bytes.reverse(); bytes.reverse();
bytes.into_iter().map(LookupReverse::swap_bits).collect() bytes.into_iter().map(LookupReverse::swap_bits).collect()
} }
/*
/// Verify that the given `bytes` faithfully represent a bitfield of length `bit_len`.
///
/// The only valid `bytes` for `bit_len == 0` is `&[0]`.
pub fn verify_bitfield_bytes(bytes: &[u8], bit_len: usize) -> bool {
if bytes.len() == 1 && bit_len == 0 && bytes == &[0] {
true // A bitfield with `bit_len` 0 can only be represented by a single zero byte.
} else if bytes.len() != ((bit_len + 7) / 8) || bytes.is_empty() {
false // The number of bytes must be the minimum required to represent `bit_len`.
} else {
// Ensure there are no bits higher than `bit_len` that are set to true.
let (mask, _) = u8::max_value().overflowing_shl(8 - (bit_len as u32 % 8));
(bytes.last().expect("Bytes cannot be empty") & !mask) == 0
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn bitfield_bytes_length() {
assert!(verify_bitfield_bytes(&[0b0000_0000], 0));
assert!(verify_bitfield_bytes(&[0b1000_0000], 1));
assert!(verify_bitfield_bytes(&[0b1100_0000], 2));
assert!(verify_bitfield_bytes(&[0b1110_0000], 3));
assert!(verify_bitfield_bytes(&[0b1111_0000], 4));
assert!(verify_bitfield_bytes(&[0b1111_1000], 5));
assert!(verify_bitfield_bytes(&[0b1111_1100], 6));
assert!(verify_bitfield_bytes(&[0b1111_1110], 7));
assert!(verify_bitfield_bytes(&[0b1111_1111], 8));
assert!(verify_bitfield_bytes(&[0b1111_1111, 0b0000_0000], 9));
assert!(verify_bitfield_bytes(&[0b1111_1111, 0b1000_0000], 9));
assert!(verify_bitfield_bytes(&[0b1111_1111, 0b1100_0000], 10));
assert!(verify_bitfield_bytes(&[0b1111_1111, 0b1110_0000], 11));
assert!(verify_bitfield_bytes(&[0b1111_1111, 0b1111_0000], 12));
assert!(verify_bitfield_bytes(&[0b1111_1111, 0b1111_1000], 13));
assert!(verify_bitfield_bytes(&[0b1111_1111, 0b1111_1100], 14));
assert!(verify_bitfield_bytes(&[0b1111_1111, 0b1111_1110], 15));
for i in 0..8 {
assert!(!verify_bitfield_bytes(&[], i));
assert!(!verify_bitfield_bytes(&[0b1111_1111], i));
assert!(!verify_bitfield_bytes(&[0b1111_1110, 0b0000_0000], i));
}
assert!(!verify_bitfield_bytes(&[0b1000_0000], 0));
assert!(!verify_bitfield_bytes(&[0b1000_0000], 0));
assert!(!verify_bitfield_bytes(&[0b1100_0000], 1));
assert!(!verify_bitfield_bytes(&[0b1110_0000], 2));
assert!(!verify_bitfield_bytes(&[0b1111_0000], 3));
assert!(!verify_bitfield_bytes(&[0b1111_1000], 4));
assert!(!verify_bitfield_bytes(&[0b1111_1100], 5));
assert!(!verify_bitfield_bytes(&[0b1111_1110], 6));
assert!(!verify_bitfield_bytes(&[0b1111_1111], 7));
assert!(!verify_bitfield_bytes(&[0b1111_1111, 0b1000_0000], 8));
assert!(!verify_bitfield_bytes(&[0b1111_1111, 0b1100_0000], 9));
assert!(!verify_bitfield_bytes(&[0b1111_1111, 0b1110_0000], 10));
assert!(!verify_bitfield_bytes(&[0b1111_1111, 0b1111_0000], 11));
assert!(!verify_bitfield_bytes(&[0b1111_1111, 0b1111_1000], 12));
assert!(!verify_bitfield_bytes(&[0b1111_1111, 0b1111_1100], 13));
assert!(!verify_bitfield_bytes(&[0b1111_1111, 0b1111_1110], 14));
assert!(!verify_bitfield_bytes(&[0b1111_1110], 6));
}
}
*/