use std::{convert::TryFrom, error::Error};
use std::{fmt, vec::Vec};
const MOST_SIGNIFICANT_BIT_PATTERN: u8 = 0b10000000;
const CLEARED_PATTERN: u8 = 0b00000000;
#[derive(Debug, PartialOrd, PartialEq, Clone)]
pub struct Bit(pub u8);
#[derive(Debug)]
pub struct BitVec(Vec<Bit>);
impl BitVec {
pub fn filled_with(bit_val: u8, length: usize) -> BitVec {
vec![bit_val]
.repeat(length)
.iter()
.map(|v| Bit(*v))
.collect::<Vec<Bit>>()
.into()
}
}
impl From<BitVec> for Vec<Bit> {
fn from(bit_vec: BitVec) -> Self {
bit_vec.0
}
}
impl From<Vec<Bit>> for BitVec {
fn from(bit_vec: Vec<Bit>) -> Self {
BitVec(bit_vec)
}
}
impl From<BitVec> for u32 {
fn from(bit_vec: BitVec) -> Self {
let mut number: u32 = 0;
for bit in bit_vec.0.into_iter() {
number <<= 1;
number += u32::from(bit.0);
}
number
}
}
impl From<u32> for BitVec {
fn from(number: u32) -> Self {
let byte_array = [
((number >> 24) & 0xff) as u8,
((number >> 16) & 0xff) as u8,
((number >> 8) & 0xff) as u8,
(number & 0xff) as u8,
];
BitIterator::new(&byte_array).collect::<Vec<Bit>>().into()
}
}
impl TryFrom<BitVec> for Vec<u8> {
type Error = BinaryConversionError;
fn try_from(bit_vec: BitVec) -> Result<Vec<u8>, Self::Error> {
let mut bytes = Vec::<u8>::default();
let mut index = 0;
if bit_vec.0.len() % 8 != 0 {
return Err(BinaryConversionError::new(
"Bit array length is not divisible by 8".to_string(),
));
}
while index < bit_vec.0.len() {
let mut byte = 0;
for _ in 0..8 {
byte *= 2;
byte += bit_vec.0.get(index).unwrap().0;
index += 1;
}
bytes.push(byte);
}
Ok(bytes)
}
}
#[cfg(not(tarpaulin_include))]
impl fmt::Display for Bit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone)]
pub struct BinaryConversionError {
message: String,
}
impl BinaryConversionError {
fn new(message: String) -> Self {
BinaryConversionError { message }
}
}
#[cfg(not(tarpaulin_include))]
impl fmt::Display for BinaryConversionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Binary conversion error")
}
}
impl Error for BinaryConversionError {}
#[derive(Debug, Copy, Clone)]
struct BinaryPattern(u8);
impl BinaryPattern {
fn new() -> BinaryPattern {
BinaryPattern(MOST_SIGNIFICANT_BIT_PATTERN)
}
fn start(&mut self) {
self.0 = MOST_SIGNIFICANT_BIT_PATTERN;
}
fn is_cleared(&self) -> bool {
self.0 == CLEARED_PATTERN
}
fn shift(&mut self) {
self.0 >>= 1;
}
fn get(&self, byte: u8) -> Bit {
match byte & self.0 {
0 => Bit(0),
_ => Bit(1),
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct BitIterator<'a> {
bytes: &'a [u8],
index: usize,
fetch_pattern: BinaryPattern,
}
impl<'a> BitIterator<'a> {
pub fn new(array: &'a [u8]) -> Self {
BitIterator {
bytes: array,
index: 0,
fetch_pattern: BinaryPattern::new(),
}
}
}
impl<'a> Iterator for BitIterator<'a> {
type Item = Bit;
fn next(&mut self) -> Option<Self::Item> {
if self.fetch_pattern.is_cleared() {
self.fetch_pattern.start();
self.index += 1;
};
let byte = *self.bytes.get(self.index)?;
let bit = self.fetch_pattern.get(byte);
self.fetch_pattern.shift();
Some(bit)
}
}