Add progress on bitfields
This commit is contained in:
parent
ecb0bf11c7
commit
636ebb0d4e
@ -75,6 +75,16 @@ impl<N: Unsigned> BitList<N> {
|
||||
pub fn max_len() -> 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> {
|
||||
@ -153,7 +163,7 @@ impl<N: Unsigned> default::Default for BitList<N> {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_bitlist {
|
||||
mod test {
|
||||
use super::*;
|
||||
use serde_yaml;
|
||||
use ssz::ssz_encode;
|
||||
|
@ -54,6 +54,18 @@ impl<N: Unsigned> BitVector<N> {
|
||||
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> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -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
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
if self.bitfield.is_empty() {
|
||||
@ -227,3 +218,74 @@ pub fn reverse_bit_order(mut bytes: Vec<u8>) -> Vec<u8> {
|
||||
bytes.reverse();
|
||||
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));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user