use std::fmt::{ self, Formatter, Debug };
use std::ops::{ Index, IndexMut };
#[derive(PartialEq)]
pub struct ByteBase2 {
intern: [bool;8]
}
#[derive(PartialEq)]
pub struct InvalidPattern;
impl Debug for InvalidPattern {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "The string pattern should have exactly 8, '0' or '1', characters.")
}
}
impl ByteBase2 {
pub fn ones(&self) -> usize {
self.intern.iter().filter(|bit| **bit).count()
}
pub fn iter(&self) -> impl Iterator<Item=bool> {
Vec::from(self.intern.as_ref()).into_iter()
}
pub fn from_string(pattern: impl Into<String>) -> Result<Self, InvalidPattern> {
let pattern = pattern.into();
if pattern.len() == 8 {
let mut intern = [false;8];
for (index, bit) in pattern.chars().rev().enumerate() {
if bit == '1' { intern[index] = true; }
else if bit != '0' { return Err(InvalidPattern); }
}
return Ok(ByteBase2 { intern });
}
Err(InvalidPattern)
}
pub fn from_dec(mut input: u8) -> Self {
let mut intern = [false;8];
for index in 0..8 {
intern[index] = input % 2 == 1;
input /= 2;
}
ByteBase2 { intern }
}
pub fn as_dec(&self) -> u8 {
let mut output = 0;
for index in 0..8 {
if self.intern[index] {
output += 2_u8.pow(index as u32);
}
}
output
}
}
impl Index<usize> for ByteBase2 {
type Output = bool;
fn index(&self, idx: usize) -> &Self::Output {
&self.intern[idx]
}
}
impl IndexMut<usize> for ByteBase2 {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
&mut self.intern[idx]
}
}
impl Debug for ByteBase2 {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let mut output = String::with_capacity(8);
for bit in self.intern.iter().rev() {
if *bit { output.push('1'); }
else { output.push('0'); }
}
write!(f, "{}", output)
}
}
#[cfg(test)]
mod test_mod {
use crate::ByteBase2;
#[test]
#[should_panic]
fn index_test() {
let byte = ByteBase2::from_dec(15);
byte[8];
}
#[test]
fn debug_test() {
assert_eq!(format!("{:?}", ByteBase2::from_dec(15)), "00001111".to_string());
}
}