use std::fmt;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct DiffMask {
mask: Vec<u8>,
}
impl DiffMask {
pub fn new(bytes: u8) -> DiffMask {
DiffMask {
mask: vec![0; bytes as usize],
}
}
pub fn bit(&self, index: u8) -> Option<bool> {
if let Some(byte) = self.mask.get((index / 8) as usize) {
let adjusted_index = index % 8;
return Some(byte & (1 << adjusted_index) != 0);
}
None
}
pub fn set_bit(&mut self, index: u8, value: bool) {
if let Some(byte) = self.mask.get_mut((index / 8) as usize) {
let adjusted_index = index % 8;
let bit_mask = 1 << adjusted_index;
if value {
*byte |= bit_mask;
} else {
*byte &= !bit_mask;
}
}
}
pub fn clear(&mut self) {
let size = self.mask.len();
self.mask = vec![0; size];
}
pub fn is_clear(&self) -> bool {
for byte in self.mask.iter() {
if *byte != 0 {
return false;
}
}
true
}
pub fn byte_number(&self) -> u8 {
self.mask.len() as u8
}
pub fn byte(&self, index: usize) -> u8 {
self.mask[index]
}
pub fn nand(&mut self, other: &DiffMask) {
if other.byte_number() != self.byte_number() {
return;
}
for n in 0..self.mask.len() {
if let Some(my_byte) = self.mask.get_mut(n) {
let other_byte = !other.byte(n);
*my_byte &= other_byte;
}
}
}
pub fn or(&mut self, other: &DiffMask) {
if other.byte_number() != self.byte_number() {
return;
}
for n in 0..self.mask.len() {
if let Some(my_byte) = self.mask.get_mut(n) {
let other_byte = other.byte(n);
*my_byte |= other_byte;
}
}
}
pub fn copy_contents(&mut self, other: &DiffMask) {
if other.byte_number() != self.byte_number() {
return;
}
for n in 0..self.mask.len() {
if let Some(my_byte) = self.mask.get_mut(n) {
let other_byte = other.byte(n);
*my_byte = other_byte;
}
}
}
}
impl fmt::Display for DiffMask {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut out_string: String = String::new();
for y in 0..8 {
if let Some(bit) = self.bit(y) {
if bit {
out_string.push('1');
} else {
out_string.push('0');
}
}
}
write!(f, "{}", out_string)
}
}
#[cfg(test)]
mod single_byte_tests {
use crate::DiffMask;
#[test]
fn getset() {
let mut mask = DiffMask::new(1);
mask.set_bit(0, true);
mask.set_bit(2, true);
mask.set_bit(4, true);
mask.set_bit(6, true);
mask.set_bit(4, false);
assert!(mask.bit(0).unwrap());
assert!(!mask.bit(1).unwrap());
assert!(mask.bit(2).unwrap());
assert!(!mask.bit(4).unwrap());
assert!(mask.bit(6).unwrap());
}
#[test]
fn clear() {
let mut mask = DiffMask::new(1);
mask.set_bit(0, true);
mask.set_bit(2, true);
mask.set_bit(4, true);
mask.set_bit(6, true);
mask.clear();
assert!(!mask.bit(0).unwrap());
assert!(!mask.bit(2).unwrap());
assert!(!mask.bit(4).unwrap());
assert!(!mask.bit(6).unwrap());
}
#[test]
fn is_clear_true() {
let mut mask = DiffMask::new(1);
mask.set_bit(2, true);
assert!(!mask.is_clear());
mask.set_bit(2, false);
assert!(mask.is_clear());
}
#[test]
fn bytes() {
let mask = DiffMask::new(1);
assert!(mask.byte_number() == 1);
}
#[test]
fn byte() {
let mut mask = DiffMask::new(1);
mask.set_bit(2, true);
let byte = mask.byte(0);
assert!(byte == 4);
}
#[test]
fn nand() {
let mut mask_a = DiffMask::new(1);
mask_a.set_bit(1, true);
mask_a.set_bit(2, true);
let mut mask_b = DiffMask::new(1);
mask_b.set_bit(1, true);
mask_a.nand(&mask_b);
assert!(!mask_a.bit(0).unwrap());
assert!(!mask_a.bit(1).unwrap());
assert!(mask_a.bit(2).unwrap());
assert!(!mask_a.bit(3).unwrap());
}
#[test]
fn or() {
let mut mask_a = DiffMask::new(1);
mask_a.set_bit(1, true);
mask_a.set_bit(2, true);
let mut mask_b = DiffMask::new(1);
mask_b.set_bit(2, true);
mask_b.set_bit(3, true);
mask_a.or(&mask_b);
assert!(!mask_a.bit(0).unwrap());
assert!(mask_a.bit(1).unwrap());
assert!(mask_a.bit(2).unwrap());
assert!(mask_a.bit(3).unwrap());
assert!(!mask_a.bit(4).unwrap());
}
#[test]
fn clone() {
let mut mask_a = DiffMask::new(1);
mask_a.set_bit(1, true);
mask_a.set_bit(4, true);
let mask_b = mask_a.clone();
assert!(mask_b.bit(1).unwrap());
assert!(!mask_b.bit(3).unwrap());
assert!(mask_b.bit(4).unwrap());
}
}
#[cfg(test)]
mod double_byte_tests {
use crate::DiffMask;
#[test]
fn getset() {
let mut mask = DiffMask::new(2);
mask.set_bit(0, true);
mask.set_bit(4, true);
mask.set_bit(8, true);
mask.set_bit(12, true);
mask.set_bit(8, false);
assert!(mask.bit(0).unwrap());
assert!(mask.bit(4).unwrap());
assert!(!mask.bit(8).unwrap());
assert!(mask.bit(12).unwrap());
assert!(!mask.bit(13).unwrap());
}
#[test]
fn clear() {
let mut mask = DiffMask::new(2);
mask.set_bit(0, true);
mask.set_bit(4, true);
mask.set_bit(8, true);
mask.set_bit(12, true);
mask.clear();
assert!(!mask.bit(0).unwrap());
assert!(!mask.bit(4).unwrap());
assert!(!mask.bit(8).unwrap());
assert!(!mask.bit(12).unwrap());
}
#[test]
fn is_clear_true() {
let mut mask = DiffMask::new(2);
mask.set_bit(9, true);
assert!(!mask.is_clear());
mask.set_bit(9, false);
assert!(mask.is_clear());
}
#[test]
fn bytes() {
let mask = DiffMask::new(2);
assert!(mask.byte_number() == 2);
}
#[test]
fn byte() {
let mut mask = DiffMask::new(2);
mask.set_bit(10, true);
let byte = mask.byte(1);
assert!(byte == 4);
}
#[test]
fn nand() {
let mut mask_a = DiffMask::new(2);
mask_a.set_bit(1, true);
mask_a.set_bit(2, true);
mask_a.set_bit(9, true);
mask_a.set_bit(10, true);
let mut mask_b = DiffMask::new(2);
mask_b.set_bit(1, true);
mask_b.set_bit(9, true);
mask_a.nand(&mask_b);
assert!(!mask_a.bit(0).unwrap());
assert!(!mask_a.bit(1).unwrap());
assert!(mask_a.bit(2).unwrap());
assert!(!mask_a.bit(3).unwrap());
assert!(!mask_a.bit(8).unwrap());
assert!(!mask_a.bit(9).unwrap());
assert!(mask_a.bit(10).unwrap());
assert!(!mask_a.bit(11).unwrap());
}
#[test]
fn or() {
let mut mask_a = DiffMask::new(2);
mask_a.set_bit(4, true);
mask_a.set_bit(8, true);
let mut mask_b = DiffMask::new(2);
mask_b.set_bit(8, true);
mask_b.set_bit(12, true);
mask_a.or(&mask_b);
assert!(!mask_a.bit(0).unwrap());
assert!(mask_a.bit(4).unwrap());
assert!(mask_a.bit(8).unwrap());
assert!(mask_a.bit(12).unwrap());
assert!(!mask_a.bit(15).unwrap());
}
#[test]
fn clone() {
let mut mask_a = DiffMask::new(2);
mask_a.set_bit(2, true);
mask_a.set_bit(10, true);
let mask_b = mask_a.clone();
assert!(mask_b.bit(2).unwrap());
assert!(!mask_b.bit(4).unwrap());
assert!(!mask_b.bit(9).unwrap());
assert!(mask_b.bit(10).unwrap());
}
}