#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Not enough bits to extract required data.")]
NotEnoughBits,
#[error("Unknown word size.")]
InvalidWordSize,
}
pub type Result<T> = std::result::Result<T, Error>;
pub fn bits_to_bytes(bits: &[bool]) -> Vec<u8> {
let mut bytes = Vec::with_capacity((bits.len() + 7) / 8);
for chunk in bits.chunks(8) {
let mut byte = 0u8;
for (idx, bit) in chunk.iter().enumerate() {
byte |= (*bit as u8) << idx;
}
bytes.push(byte);
}
bytes
}
pub fn bytes_to_bits(bytes: &[u8], mut n: usize) -> Result<Vec<bool>> {
if n == 0 {
return Ok(Vec::new());
}
let mut bits = Vec::with_capacity(n);
for byte in bytes {
for i in 0..8 {
bits.push((byte >> i) & 1 == 1);
n -= 1;
if n == 0 {
return Ok(bits);
}
}
}
Err(Error::NotEnoughBits)
}
pub fn byte_to_bits(byte: u8) -> Vec<bool> {
match bytes_to_bits(&[byte], 8) {
Ok(bits) => bits,
_ => unreachable!(),
}
}
pub fn drain_word(bits: &[bool], n: usize) -> Result<(u64, &[bool])> {
if bits.len() < n {
Err(Error::NotEnoughBits)
} else if n > 64 {
Err(Error::InvalidWordSize)
} else {
let mut word = 0u64;
for (idx, bit) in bits[..n].iter().enumerate() {
word |= (*bit as u64) << idx;
}
Ok((word, &bits[n..]))
}
}
pub fn drain_bit(bits: &[bool]) -> Result<(u8, &[bool])> {
let (word, bits) = drain_word(bits, 1)?;
Ok((word as u8, bits))
}
pub fn drain_u8(bits: &[bool]) -> Result<(u8, &[bool])> {
let (word, bits) = drain_word(bits, 8)?;
Ok((word as u8, bits))
}
pub fn drain_u16(bits: &[bool]) -> Result<(u16, &[bool])> {
let (word, bits) = drain_word(bits, 16)?;
Ok((word as u16, bits))
}
pub fn drain_u32(bits: &[bool]) -> Result<(u32, &[bool])> {
let (word, bits) = drain_word(bits, 32)?;
Ok((word as u32, bits))
}
pub fn append_word(bits: &mut Vec<bool>, word: u64, n: usize) {
for idx in 0..n {
let bit = ((word >> idx) & 1) == 1;
bits.push(bit);
}
}
pub fn append_bit(bits: &mut Vec<bool>, bit: u8) {
append_word(bits, bit as u64, 1)
}
pub fn append_u8(bits: &mut Vec<bool>, word: u8) {
append_word(bits, word as u64, 8)
}
pub fn append_u16(bits: &mut Vec<bool>, word: u16) {
append_word(bits, word as u64, 16)
}
pub fn append_u32(bits: &mut Vec<bool>, word: u32) {
append_word(bits, word as u64, 32)
}
macro_rules! bv {
($($x:expr),*) => {
&[ $(($x != 0),)* ] as &[bool]
}
}
#[test]
fn test_bits_to_bytes() {
assert_eq!(bits_to_bytes(&[]), vec![]);
assert_eq!(bits_to_bytes(bv![1, 1, 1, 0]), vec![0x07]);
assert_eq!(bits_to_bytes(bv![1, 1, 1, 0, 0, 1, 0, 0]), vec![0x27]);
assert_eq!(bits_to_bytes(bv![1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1]), vec![0x27, 0x08]);
}
#[test]
fn test_bytes_to_bits() {
assert_eq!(bytes_to_bits(&[0xFF], 1).unwrap(), bv![1]);
assert_eq!(bytes_to_bits(&[0xFF], 8).unwrap(), bv![1, 1, 1, 1, 1, 1, 1, 1]);
assert_eq!(bytes_to_bits(&[0xFF, 0x01], 10).unwrap(), bv![1, 1, 1, 1, 1, 1, 1, 1, 1, 0]);
assert!(bytes_to_bits(&[0xFF], 9).is_err());
}
#[test]
fn test_drain_word() {
assert_eq!(drain_word(bv![1, 0 ], 2).unwrap(), (0b01, bv![]));
assert_eq!(drain_word(bv![1, 0, 1], 2).unwrap(), (0b01, bv![1]));
assert!(drain_word(bv![1, 0, 1], 4).is_err());
}
#[test]
fn test_drain_bit() {
assert_eq!(drain_bit(bv![1 ]).unwrap(), (1, bv![]));
assert_eq!(drain_bit(bv![0, 1]).unwrap(), (0, bv![1]));
}
#[test]
fn test_drain_u8() {
assert_eq!(drain_u8(bv![1, 0, 0, 0, 1, 0, 1, 0 ]).unwrap(), (0x51, bv![]));
assert_eq!(drain_u8(bv![1, 0, 0, 0, 1, 0, 1, 0, 1, 1]).unwrap(), (0x51, bv![1, 1]));
}
#[test]
fn test_drain_u16() {
assert_eq!(drain_u16(bv![1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0]).unwrap(),
(0x4351, bv![]));
assert_eq!(drain_u16(bv![1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1]).unwrap(),
(0x4351, bv![0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1]));
}
#[test]
fn test_drain_u32() {
assert_eq!(drain_u32(bv![1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1]).unwrap(),
(0xBCAE4351, bv![]));
}
#[test]
fn test_append_word() {
let mut bits = bv![1, 1, 1, 1].to_vec();
append_word(&mut bits, 0b1101, 4);
assert_eq!(&bits[..], bv![1, 1, 1, 1, 1, 0, 1, 1]);
}
#[test]
fn test_append_bit() {
let mut bits = bv![1, 1, 1, 1].to_vec();
append_bit(&mut bits, 0);
assert_eq!(&bits[..], bv![1, 1, 1, 1, 0]);
}
#[test]
fn test_append_u8() {
let mut bits = bv![1, 1, 1, 1].to_vec();
append_u8(&mut bits, 0x81);
assert_eq!(&bits[..], bv![1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1]);
}
#[test]
fn test_append_u16() {
let mut bits = bv![1, 1, 1, 1].to_vec();
append_u16(&mut bits, 0x55AA);
assert_eq!(&bits[..], bv![1, 1, 1, 1,
0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0]);
}
#[test]
fn test_append_u32() {
let mut bits = bv![1, 1, 1, 1].to_vec();
append_u32(&mut bits, 0x76543210);
assert_eq!(&bits[..], bv![1, 1, 1, 1,
0, 0, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 1, 1, 0, 0,
0, 0, 1, 0, 1, 0, 1, 0,
0, 1, 1, 0, 1, 1, 1, 0]);
}