use once_cell::sync::Lazy;
use regex::Regex;
use crate::{
common::{BitArray, Result},
Exceptions,
};
static ONE: Lazy<Regex> = Lazy::new(|| Regex::new("1").unwrap());
static ZERO: Lazy<Regex> = Lazy::new(|| Regex::new("0").unwrap());
static SPACE: Lazy<Regex> = Lazy::new(|| Regex::new(" ").unwrap());
pub fn buildBitArrayFromString(data: &str) -> Result<BitArray> {
let dotsAndXs = ZERO
.replace_all(&ONE.replace_all(data, "X"), ".")
.to_string();
let mut binary = BitArray::with_size(SPACE.replace_all(&dotsAndXs, "").chars().count());
let mut counter = 0;
for i in 0..dotsAndXs.chars().count() {
if i % 9 == 0 {
if dotsAndXs.chars().nth(i).ok_or(Exceptions::PARSE)? != ' ' {
return Err(Exceptions::illegal_state_with("space expected"));
}
continue;
}
let currentChar = dotsAndXs.chars().nth(i).ok_or(Exceptions::PARSE)?;
if currentChar == 'X' || currentChar == 'x' {
binary.set(counter);
}
counter += 1;
}
Ok(binary)
}
pub fn buildBitArrayFromStringWithoutSpaces(data: &str) -> Result<BitArray> {
let mut sb = String::new();
let dotsAndXs = ZERO
.replace_all(&ONE.replace_all(data, "X"), ".")
.to_string();
let mut current = 0;
let dotsAndXs_length = dotsAndXs.chars().count();
while current < dotsAndXs_length {
sb.push(' ');
let mut i = 0;
while i < 8 && current < dotsAndXs_length {
sb.push(dotsAndXs.chars().nth(current).ok_or(Exceptions::PARSE)?);
current += 1;
i += 1;
}
}
buildBitArrayFromString(&sb)
}
#[cfg(test)]
mod BinaryUtilTest {
#[test]
fn testBuildBitArrayFromString() {
let data = " ..X..X.. ..XXX... XXXXXXXX ........";
check(data);
let data = " XXX..X..";
check(data);
let data = " XX";
check(data);
let data = " ....XX.. ..XX";
check(data);
let data = " ....XX.. ..XX..XX ....X.X. ........";
check(data);
}
fn check(data: &str) {
let binary = super::buildBitArrayFromString(data).expect("check");
assert_eq!(data, binary.to_string());
}
#[test]
fn testBuildBitArrayFromStringWithoutSpaces() {
let data = " ..X..X.. ..XXX... XXXXXXXX ........";
checkWithoutSpaces(data);
let data = " XXX..X..";
checkWithoutSpaces(data);
let data = " XX";
checkWithoutSpaces(data);
let data = " ....XX.. ..XX";
checkWithoutSpaces(data);
let data = " ....XX.. ..XX..XX ....X.X. ........";
checkWithoutSpaces(data);
}
fn checkWithoutSpaces(data: &str) {
let dataWithoutSpaces = super::SPACE.replace_all(data, "");
let binary =
super::buildBitArrayFromStringWithoutSpaces(&dataWithoutSpaces).expect("success");
assert_eq!(data, binary.to_string());
}
}