2018-10-24 10:21:51 +00:00
extern crate bit_vec ;
2018-09-22 04:07:14 +00:00
extern crate ssz ;
2018-10-24 10:21:51 +00:00
use bit_vec ::BitVec ;
2018-07-12 04:59:50 +00:00
2018-11-15 17:19:59 +00:00
use std ::default ;
2018-10-24 10:21:51 +00:00
/// A BooleanBitfield represents a set of booleans compactly stored as a vector of bits.
2018-11-15 17:19:59 +00:00
/// The BooleanBitfield is given a fixed size during construction. Reads outside of the current size return an out-of-bounds error. Writes outside of the current size expand the size of the set.
2018-10-24 10:21:51 +00:00
#[ derive(Debug, Clone, PartialEq) ]
pub struct BooleanBitfield ( BitVec ) ;
/// Error represents some reason a request against a bitfield was not satisfied
2018-11-22 21:57:28 +00:00
#[ derive(Debug, PartialEq) ]
2018-10-24 10:21:51 +00:00
pub enum Error {
/// OutOfBounds refers to indexing into a bitfield where no bits exist; returns the illegal index and the current size of the bitfield, respectively
OutOfBounds ( usize , usize ) ,
2018-07-12 04:59:50 +00:00
}
impl BooleanBitfield {
2018-11-15 17:19:59 +00:00
/// Create a new bitfield.
2018-07-12 04:59:50 +00:00
pub fn new ( ) -> Self {
2018-11-15 17:19:59 +00:00
Default ::default ( )
}
/// Create a new bitfield with the given length `initial_len` and all values set to `bit`.
pub fn from_elem ( inital_len : usize , bit : bool ) -> Self {
Self {
0 : BitVec ::from_elem ( inital_len , bit ) ,
}
2018-07-12 04:59:50 +00:00
}
2018-09-10 05:50:35 +00:00
2018-10-24 10:21:51 +00:00
/// Create a new bitfield using the supplied `bytes` as input
2018-11-15 17:19:59 +00:00
pub fn from_bytes ( bytes : & [ u8 ] ) -> Self {
2018-10-24 10:21:51 +00:00
Self {
0 : BitVec ::from_bytes ( bytes ) ,
}
2018-07-12 04:59:50 +00:00
}
2018-09-10 05:50:35 +00:00
/// Read the value of a bit.
///
2018-10-24 10:21:51 +00:00
/// If the index is in bounds, then result is Ok(value) where value is `true` if the bit is 1 and `false` if the bit is 0.
/// If the index is out of bounds, we return an error to that extent.
pub fn get ( & self , i : usize ) -> Result < bool , Error > {
match self . 0. get ( i ) {
Some ( value ) = > Ok ( value ) ,
None = > Err ( Error ::OutOfBounds ( i , self . 0. len ( ) ) ) ,
2018-07-12 04:59:50 +00:00
}
}
2018-09-10 05:50:35 +00:00
/// Set the value of a bit.
///
2018-11-15 17:19:59 +00:00
/// If the index is out of bounds, we expand the size of the underlying set to include the new index.
/// Returns the previous value if there was one.
pub fn set ( & mut self , i : usize , value : bool ) -> Option < bool > {
let previous = match self . get ( i ) {
Ok ( previous ) = > Some ( previous ) ,
Err ( Error ::OutOfBounds ( _ , len ) ) = > {
let new_len = i - len + 1 ;
self . 0. grow ( new_len , false ) ;
None
}
} ;
2018-10-24 10:21:51 +00:00
self . 0. set ( i , value ) ;
2018-11-15 17:19:59 +00:00
previous
2018-07-12 08:19:20 +00:00
}
2018-09-10 05:50:35 +00:00
2018-10-24 10:21:51 +00:00
/// Returns the index of the highest set bit. Some(n) if some bit is set, None otherwise.
pub fn highest_set_bit ( & self ) -> Option < usize > {
self . 0. iter ( ) . rposition ( | bit | bit )
2018-09-24 08:06:47 +00:00
}
2018-10-24 10:21:51 +00:00
/// Returns the number of bits in this bitfield.
pub fn len ( & self ) -> usize {
self . 0. len ( )
2018-09-22 04:07:14 +00:00
}
2018-11-20 18:12:49 +00:00
/// Returns the number of bytes required to represent this bitfield.
pub fn num_bytes ( & self ) -> usize {
self . to_bytes ( ) . len ( )
}
2018-10-24 10:21:51 +00:00
/// Returns the number of `1` bits in the bitfield
pub fn num_set_bits ( & self ) -> usize {
self . 0. iter ( ) . filter ( | & bit | bit ) . count ( )
2018-07-17 03:21:28 +00:00
}
2018-10-24 10:21:51 +00:00
/// Returns a vector of bytes representing the bitfield
2018-11-20 20:27:44 +00:00
/// Note that this returns the bit layout of the underlying implementation in the `bit-vec` crate.
2018-10-24 10:21:51 +00:00
pub fn to_bytes ( & self ) -> Vec < u8 > {
self . 0. to_bytes ( )
2018-09-22 04:07:14 +00:00
}
}
2018-11-15 17:19:59 +00:00
impl default ::Default for BooleanBitfield {
/// default provides the "empty" bitfield
/// Note: the empty bitfield is set to the `0` byte.
fn default ( ) -> Self {
Self ::from_elem ( 8 , false )
}
}
2018-11-20 20:27:44 +00:00
// borrowed from bit_vec crate
fn reverse_bits ( byte : u8 ) -> u8 {
let mut result = 0 ;
for i in 0 .. 8 {
result = result | ( ( byte > > i ) & 1 ) < < ( 7 - i ) ;
}
result
}
impl ssz ::Encodable for BooleanBitfield {
// ssz_append encodes Self according to the `ssz` spec.
// Note that we have to flip the endianness of the encoding with `reverse_bits` to account for an implementation detail of `bit-vec` crate.
fn ssz_append ( & self , s : & mut ssz ::SszStream ) {
let bytes : Vec < u8 > = self
. to_bytes ( )
. iter ( )
. map ( | & byte | reverse_bits ( byte ) )
. collect ( ) ;
s . append_vec ( & bytes ) ;
}
}
2018-09-22 04:07:14 +00:00
impl ssz ::Decodable for BooleanBitfield {
2018-11-04 14:35:00 +00:00
fn ssz_decode ( bytes : & [ u8 ] , index : usize ) -> Result < ( Self , usize ) , ssz ::DecodeError > {
let len = ssz ::decode ::decode_length ( bytes , index , ssz ::LENGTH_BYTES ) ? ;
2018-09-22 04:07:14 +00:00
if ( ssz ::LENGTH_BYTES + len ) > bytes . len ( ) {
return Err ( ssz ::DecodeError ::TooShort ) ;
}
2018-10-24 10:21:51 +00:00
2018-09-22 04:07:14 +00:00
if len = = 0 {
2018-11-04 14:35:00 +00:00
Ok ( ( BooleanBitfield ::new ( ) , index + ssz ::LENGTH_BYTES ) )
2018-09-22 04:07:14 +00:00
} else {
2018-11-20 20:27:44 +00:00
let bytes = & bytes [ ( index + 4 ) .. ( index + len + 4 ) ] ;
let mut field = BooleanBitfield ::from_elem ( 0 , false ) ;
for ( byte_index , byte ) in bytes . iter ( ) . enumerate ( ) {
for i in 0 .. 8 {
let bit = byte & ( 1 < < i ) ;
if bit ! = 0 {
field . set ( 8 * byte_index + i , true ) ;
}
}
}
2018-09-22 04:07:14 +00:00
let index = index + ssz ::LENGTH_BYTES + len ;
2018-10-24 10:21:51 +00:00
Ok ( ( field , index ) )
2018-09-22 04:07:14 +00:00
}
}
}
2018-07-12 04:59:50 +00:00
#[ cfg(test) ]
mod tests {
use super ::* ;
2018-11-20 20:27:44 +00:00
use ssz ::SszStream ;
2018-09-22 04:07:14 +00:00
2018-09-30 04:54:03 +00:00
#[ test ]
2018-11-22 21:57:28 +00:00
fn test_new_bitfield ( ) {
2018-10-24 10:21:51 +00:00
let mut field = BooleanBitfield ::new ( ) ;
2018-11-15 17:19:59 +00:00
let original_len = field . len ( ) ;
for i in 0 .. 100 {
if i < original_len {
assert! ( ! field . get ( i ) . unwrap ( ) ) ;
} else {
assert! ( field . get ( i ) . is_err ( ) ) ;
}
let previous = field . set ( i , true ) ;
if i < original_len {
assert! ( ! previous . unwrap ( ) ) ;
} else {
assert! ( previous . is_none ( ) ) ;
}
2018-10-24 10:21:51 +00:00
}
}
2018-09-30 04:54:03 +00:00
2018-11-22 21:57:28 +00:00
#[ test ]
fn test_empty_bitfield ( ) {
let mut field = BooleanBitfield ::from_elem ( 0 , false ) ;
let original_len = field . len ( ) ;
assert_eq! ( original_len , 0 ) ;
for i in 0 .. 100 {
if i < original_len {
assert! ( ! field . get ( i ) . unwrap ( ) ) ;
} else {
assert! ( field . get ( i ) . is_err ( ) ) ;
}
let previous = field . set ( i , true ) ;
if i < original_len {
assert! ( ! previous . unwrap ( ) ) ;
} else {
assert! ( previous . is_none ( ) ) ;
}
}
assert_eq! ( field . len ( ) , 100 ) ;
assert_eq! ( field . num_set_bits ( ) , 100 ) ;
}
2018-10-24 10:21:51 +00:00
const INPUT : & [ u8 ] = & [ 0b0000_0010 , 0b0000_0010 ] ;
2018-09-30 04:54:03 +00:00
2018-10-24 10:21:51 +00:00
#[ test ]
fn test_get_from_bitfield ( ) {
2018-11-15 17:19:59 +00:00
let field = BooleanBitfield ::from_bytes ( INPUT ) ;
2018-10-24 10:21:51 +00:00
let unset = field . get ( 0 ) . unwrap ( ) ;
assert! ( ! unset ) ;
let set = field . get ( 6 ) . unwrap ( ) ;
assert! ( set ) ;
let set = field . get ( 14 ) . unwrap ( ) ;
assert! ( set ) ;
2018-09-30 04:54:03 +00:00
}
2018-09-22 04:07:14 +00:00
#[ test ]
2018-10-24 10:21:51 +00:00
fn test_set_for_bitfield ( ) {
2018-11-15 17:19:59 +00:00
let mut field = BooleanBitfield ::from_bytes ( INPUT ) ;
2018-10-24 10:21:51 +00:00
let previous = field . set ( 10 , true ) . unwrap ( ) ;
assert! ( ! previous ) ;
let previous = field . get ( 10 ) . unwrap ( ) ;
assert! ( previous ) ;
let previous = field . set ( 6 , false ) . unwrap ( ) ;
assert! ( previous ) ;
let previous = field . get ( 6 ) . unwrap ( ) ;
assert! ( ! previous ) ;
2018-09-22 04:07:14 +00:00
}
#[ test ]
2018-10-24 10:21:51 +00:00
fn test_highest_set_bit ( ) {
2018-11-15 17:19:59 +00:00
let field = BooleanBitfield ::from_bytes ( INPUT ) ;
2018-10-24 10:21:51 +00:00
assert_eq! ( field . highest_set_bit ( ) . unwrap ( ) , 14 ) ;
2018-09-22 04:07:14 +00:00
2018-11-22 21:57:28 +00:00
let field = BooleanBitfield ::from_bytes ( & [ 0b0000_0011 ] ) ;
assert_eq! ( field . highest_set_bit ( ) . unwrap ( ) , 7 ) ;
2018-10-24 10:21:51 +00:00
let field = BooleanBitfield ::new ( ) ;
assert_eq! ( field . highest_set_bit ( ) , None ) ;
2018-09-22 04:07:14 +00:00
}
#[ test ]
2018-10-24 10:21:51 +00:00
fn test_len ( ) {
2018-11-15 17:19:59 +00:00
let field = BooleanBitfield ::from_bytes ( INPUT ) ;
2018-10-24 10:21:51 +00:00
assert_eq! ( field . len ( ) , 16 ) ;
2018-09-22 04:07:14 +00:00
2018-10-24 10:21:51 +00:00
let field = BooleanBitfield ::new ( ) ;
2018-11-15 17:19:59 +00:00
assert_eq! ( field . len ( ) , 8 ) ;
2018-09-22 04:07:14 +00:00
}
2018-07-12 04:59:50 +00:00
#[ test ]
2018-10-24 10:21:51 +00:00
fn test_num_set_bits ( ) {
2018-11-15 17:19:59 +00:00
let field = BooleanBitfield ::from_bytes ( INPUT ) ;
2018-10-24 10:21:51 +00:00
assert_eq! ( field . num_set_bits ( ) , 2 ) ;
2018-09-10 05:50:35 +00:00
2018-10-24 10:21:51 +00:00
let field = BooleanBitfield ::new ( ) ;
assert_eq! ( field . num_set_bits ( ) , 0 ) ;
2018-07-12 04:59:50 +00:00
}
#[ test ]
2018-10-24 10:21:51 +00:00
fn test_to_bytes ( ) {
2018-11-15 17:19:59 +00:00
let field = BooleanBitfield ::from_bytes ( INPUT ) ;
2018-10-24 10:21:51 +00:00
assert_eq! ( field . to_bytes ( ) , INPUT ) ;
2018-09-10 05:50:35 +00:00
2018-10-24 10:21:51 +00:00
let field = BooleanBitfield ::new ( ) ;
2018-11-15 17:19:59 +00:00
assert_eq! ( field . to_bytes ( ) , vec! [ 0 ] ) ;
}
#[ test ]
fn test_out_of_bounds ( ) {
let mut field = BooleanBitfield ::from_bytes ( INPUT ) ;
let out_of_bounds_index = field . len ( ) ;
assert! ( field . set ( out_of_bounds_index , true ) . is_none ( ) ) ;
2018-11-20 18:12:49 +00:00
assert! ( field . len ( ) = = out_of_bounds_index + 1 ) ;
2018-11-15 17:19:59 +00:00
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_some ( ) ) ;
} else {
assert! ( field . set ( i , true ) . is_none ( ) ) ;
}
}
2018-07-12 08:19:20 +00:00
}
2018-11-20 18:12:49 +00:00
2018-11-22 21:57:28 +00:00
#[ test ]
fn test_grows_with_false ( ) {
let input_all_set : & [ u8 ] = & [ 0b1111_1111 , 0b1111_1111 ] ;
let mut field = BooleanBitfield ::from_bytes ( input_all_set ) ;
// 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`. Also, for test integrity, ensure it was previously out-of-bounds.
assert! ( field . set ( b , true ) . is_none ( ) ) ;
// 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 ) ) ;
}
2018-11-20 18:12:49 +00:00
#[ test ]
fn test_num_bytes ( ) {
let field = BooleanBitfield ::from_bytes ( INPUT ) ;
assert_eq! ( field . num_bytes ( ) , 2 ) ;
let field = BooleanBitfield ::from_elem ( 2 , true ) ;
assert_eq! ( field . num_bytes ( ) , 1 ) ;
let field = BooleanBitfield ::from_elem ( 13 , true ) ;
assert_eq! ( field . num_bytes ( ) , 2 ) ;
}
2018-11-20 20:27:44 +00:00
#[ test ]
fn test_ssz_encode ( ) {
let field = BooleanBitfield ::from_elem ( 5 , true ) ;
let mut stream = SszStream ::new ( ) ;
stream . append ( & field ) ;
assert_eq! ( stream . drain ( ) , vec! [ 0 , 0 , 0 , 1 , 31 ] ) ;
let field = BooleanBitfield ::from_elem ( 18 , true ) ;
let mut stream = SszStream ::new ( ) ;
stream . append ( & field ) ;
assert_eq! ( stream . drain ( ) , vec! [ 0 , 0 , 0 , 3 , 255 , 255 , 3 ] ) ;
}
#[ test ]
fn test_ssz_decode ( ) {
let encoded = vec! [ 0 , 0 , 0 , 1 , 31 ] ;
let ( field , _ ) : ( BooleanBitfield , usize ) = ssz ::decode_ssz ( & encoded , 0 ) . unwrap ( ) ;
let expected = BooleanBitfield ::from_elem ( 5 , true ) ;
assert_eq! ( field , expected ) ;
let encoded = vec! [ 0 , 0 , 0 , 3 , 255 , 255 , 3 ] ;
let ( field , _ ) : ( BooleanBitfield , usize ) = ssz ::decode_ssz ( & encoded , 0 ) . unwrap ( ) ;
let expected = BooleanBitfield ::from_elem ( 18 , true ) ;
assert_eq! ( field , expected ) ;
}
2018-07-12 04:59:50 +00:00
}