Add tests for BitList
This commit is contained in:
parent
e4ef0fc9d4
commit
000d941e2e
@ -71,8 +71,10 @@ pub struct Bitfield<T> {
|
||||
impl<N: Unsigned + Clone> Bitfield<BitList<N>> {
|
||||
pub fn with_capacity(num_bits: usize) -> Option<Self> {
|
||||
if num_bits <= N::to_usize() {
|
||||
let num_bytes = std::cmp::max(bytes_for_bit_len(num_bits), 1);
|
||||
|
||||
Some(Self {
|
||||
bytes: vec![0; bytes_for_bit_len(num_bits)],
|
||||
bytes: vec![0; num_bytes],
|
||||
len: num_bits,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
@ -81,7 +83,7 @@ impl<N: Unsigned + Clone> Bitfield<BitList<N>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capacity() -> usize {
|
||||
pub fn max_len() -> usize {
|
||||
N::to_usize()
|
||||
}
|
||||
|
||||
@ -89,15 +91,13 @@ impl<N: Unsigned + Clone> Bitfield<BitList<N>> {
|
||||
let len = self.len();
|
||||
let mut bytes = self.as_slice().to_vec();
|
||||
|
||||
if bytes_for_bit_len(len + 1) == bytes.len() + 1 {
|
||||
while bytes_for_bit_len(len + 1) > bytes.len() {
|
||||
bytes.insert(0, 0);
|
||||
}
|
||||
|
||||
let mut bitfield: Bitfield<BitList<N>> = Bitfield::from_raw_bytes(bytes, len + 1)
|
||||
.expect("Bitfield capacity has been confirmed earlier.");
|
||||
bitfield
|
||||
.set(len, true)
|
||||
.expect("Bitfield capacity has been confirmed earlier.");
|
||||
bitfield.set(len, true).expect("Bitfield index must exist.");
|
||||
|
||||
bitfield.bytes
|
||||
}
|
||||
@ -110,17 +110,22 @@ impl<N: Unsigned + Clone> Bitfield<BitList<N>> {
|
||||
};
|
||||
|
||||
let len = initial_bitfield.highest_set_bit()?;
|
||||
initial_bitfield
|
||||
.set(len, false)
|
||||
.expect("Bit has been confirmed to exist");
|
||||
|
||||
let mut bytes = initial_bitfield.to_raw_bytes();
|
||||
if len <= Self::max_len() {
|
||||
initial_bitfield
|
||||
.set(len, false)
|
||||
.expect("Bit has been confirmed to exist");
|
||||
|
||||
if bytes_for_bit_len(len) < bytes.len() {
|
||||
bytes.remove(0);
|
||||
let mut bytes = initial_bitfield.to_raw_bytes();
|
||||
|
||||
if bytes_for_bit_len(len) < bytes.len() && bytes != &[0] {
|
||||
bytes.remove(0);
|
||||
}
|
||||
|
||||
Self::from_raw_bytes(bytes, len)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
Self::from_raw_bytes(bytes, len)
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,7 +208,7 @@ impl<T: BitfieldBehaviour> Bitfield<T> {
|
||||
&self.bytes
|
||||
}
|
||||
|
||||
pub fn from_raw_bytes(bytes: Vec<u8>, bit_len: usize) -> Option<Self> {
|
||||
fn from_raw_bytes(bytes: Vec<u8>, bit_len: usize) -> Option<Self> {
|
||||
if bytes.len() == 1 && bit_len == 0 && bytes == &[0] {
|
||||
// A bitfield with `bit_len` 0 can only be represented by a single zero byte.
|
||||
Some(Self {
|
||||
@ -552,7 +557,137 @@ impl<N: Unsigned + Clone> cached_tree_hash::CachedTreeHash for Bitfield<BitVecto
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
type Bitfield = super::Bitfield<BitList<typenum::U1024>>;
|
||||
mod bitlist {
|
||||
use super::*;
|
||||
|
||||
pub type BitList<N> = crate::Bitfield<crate::BitList<N>>;
|
||||
pub type BitList0 = BitList<typenum::U0>;
|
||||
pub type BitList1 = BitList<typenum::U1>;
|
||||
pub type BitList8 = BitList<typenum::U8>;
|
||||
pub type BitList16 = BitList<typenum::U16>;
|
||||
|
||||
#[test]
|
||||
fn ssz_encode() {
|
||||
assert_eq!(
|
||||
BitList0::with_capacity(0).unwrap().as_ssz_bytes(),
|
||||
vec![0b0000_00001],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
BitList1::with_capacity(0).unwrap().as_ssz_bytes(),
|
||||
vec![0b0000_00001],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
BitList1::with_capacity(1).unwrap().as_ssz_bytes(),
|
||||
vec![0b0000_00010],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
BitList8::with_capacity(8).unwrap().as_ssz_bytes(),
|
||||
vec![0b0000_0001, 0b0000_0000],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
BitList8::with_capacity(7).unwrap().as_ssz_bytes(),
|
||||
vec![0b1000_0000]
|
||||
);
|
||||
|
||||
let mut b = BitList8::with_capacity(8).unwrap();
|
||||
for i in 0..8 {
|
||||
b.set(i, true).unwrap();
|
||||
}
|
||||
assert_eq!(b.as_ssz_bytes(), vec![0b0000_0001, 255]);
|
||||
|
||||
let mut b = BitList8::with_capacity(8).unwrap();
|
||||
for i in 0..4 {
|
||||
b.set(i, true).unwrap();
|
||||
}
|
||||
assert_eq!(b.as_ssz_bytes(), vec![0b0000_0001, 0b0000_1111]);
|
||||
|
||||
assert_eq!(
|
||||
BitList16::with_capacity(16).unwrap().as_ssz_bytes(),
|
||||
vec![0b0000_0001, 0b0000_0000, 0b0000_0000]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssz_decode() {
|
||||
assert!(BitList0::from_ssz_bytes(&[0b0000_0000]).is_err());
|
||||
assert!(BitList1::from_ssz_bytes(&[0b0000_0000, 0b0000_0000]).is_err());
|
||||
assert!(BitList8::from_ssz_bytes(&[0b0000_0000]).is_err());
|
||||
assert!(BitList16::from_ssz_bytes(&[0b0000_0000]).is_err());
|
||||
|
||||
assert!(BitList0::from_ssz_bytes(&[0b0000_0001]).is_ok());
|
||||
assert!(BitList0::from_ssz_bytes(&[0b0000_0010]).is_err());
|
||||
|
||||
assert!(BitList1::from_ssz_bytes(&[0b0000_0001]).is_ok());
|
||||
assert!(BitList1::from_ssz_bytes(&[0b0000_0010]).is_ok());
|
||||
assert!(BitList1::from_ssz_bytes(&[0b0000_0100]).is_err());
|
||||
|
||||
assert!(BitList8::from_ssz_bytes(&[0b0000_0001]).is_ok());
|
||||
assert!(BitList8::from_ssz_bytes(&[0b0000_0010]).is_ok());
|
||||
assert!(BitList8::from_ssz_bytes(&[0b0000_0001, 0b0000_0100]).is_ok());
|
||||
assert!(BitList8::from_ssz_bytes(&[0b0000_0010, 0b0000_0100]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssz_round_trip() {
|
||||
assert_round_trip(BitList0::with_capacity(0).unwrap());
|
||||
|
||||
for i in 0..2 {
|
||||
assert_round_trip(BitList1::with_capacity(i).unwrap());
|
||||
}
|
||||
for i in 0..9 {
|
||||
assert_round_trip(BitList8::with_capacity(i).unwrap());
|
||||
}
|
||||
for i in 0..17 {
|
||||
assert_round_trip(BitList16::with_capacity(i).unwrap());
|
||||
}
|
||||
|
||||
let mut b = BitList1::with_capacity(1).unwrap();
|
||||
b.set(0, true);
|
||||
assert_round_trip(b);
|
||||
|
||||
for i in 0..8 {
|
||||
let mut b = BitList8::with_capacity(i).unwrap();
|
||||
for j in 0..i {
|
||||
if j % 2 == 0 {
|
||||
b.set(j, true);
|
||||
}
|
||||
}
|
||||
assert_round_trip(b);
|
||||
|
||||
let mut b = BitList8::with_capacity(i).unwrap();
|
||||
for j in 0..i {
|
||||
b.set(j, true);
|
||||
}
|
||||
assert_round_trip(b);
|
||||
}
|
||||
|
||||
for i in 0..16 {
|
||||
let mut b = BitList16::with_capacity(i).unwrap();
|
||||
for j in 0..i {
|
||||
if j % 2 == 0 {
|
||||
b.set(j, true);
|
||||
}
|
||||
}
|
||||
assert_round_trip(b);
|
||||
|
||||
let mut b = BitList16::with_capacity(i).unwrap();
|
||||
for j in 0..i {
|
||||
b.set(j, true);
|
||||
}
|
||||
assert_round_trip(b);
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_round_trip<T: Encode + Decode + PartialEq + std::fmt::Debug>(t: T) {
|
||||
assert_eq!(T::from_ssz_bytes(&t.as_ssz_bytes()).unwrap(), t);
|
||||
}
|
||||
}
|
||||
|
||||
type Bitfield = crate::Bitfield<BitList<typenum::U1024>>;
|
||||
|
||||
#[test]
|
||||
fn from_raw_bytes() {
|
||||
|
Loading…
Reference in New Issue
Block a user