use std::io::{BufRead, BufReader, Read, Write};
pub fn read_patterns<R: Read>(r: R) -> Result<Vec<Vec<Vec<bool>>>, String> {
let mut ret = Vec::new();
let mut pattern_ind: usize = 1;
let mut line_ind = 0;
for l in BufReader::new(r).lines() {
if let Ok(s) = l {
line_ind += 1;
let t = s.trim();
if t.is_empty() || t.starts_with('*') {
continue;
}
let sp = t.split(':').collect::<Vec<_>>();
if sp.len() >= 3 || sp.is_empty() {
return Err(
"Expected line of the form INDEX: TIMESTEP_1 TIMESTEP_2 ... TIMESTEP_N"
.to_owned(),
);
}
if sp.len() == 2 {
let parse_ind = sp[0].trim().parse::<usize>();
if parse_ind.is_err() || parse_ind.unwrap() != pattern_ind {
println!(
"Index {} on a line does not match expected {}",
sp[0], pattern_ind
);
}
}
let patterns = if sp.len() == 2 {
sp[1].split_whitespace()
} else {
sp[0].split_whitespace()
};
let mut invalid = false;
let mut seq_ret = Vec::new();
for p in patterns {
let mut comb_ret = Vec::new();
for c in p.chars() {
if c == '0' {
comb_ret.push(false);
} else if c == '1' {
comb_ret.push(true);
} else if !invalid {
invalid = true;
println!("Ignoring line {line_ind} with invalid characters");
}
}
seq_ret.push(comb_ret);
}
if !invalid {
ret.push(seq_ret);
pattern_ind += 1;
}
}
}
Ok(ret)
}
pub fn write_patterns<W: Write>(w: &mut W, patterns: &Vec<Vec<Vec<bool>>>) {
writeln!(w, "* Test pattern file").unwrap();
writeln!(w, "* generated by quaigh").unwrap();
for (i, v) in patterns.iter().enumerate() {
write!(w, "{}:", i + 1).unwrap();
for seq_pattern in v {
write!(w, " ").unwrap();
for inp_value in seq_pattern {
write!(w, "{}", if *inp_value { "1" } else { "0" }).unwrap();
}
}
writeln!(w).unwrap();
}
}
mod test {
#[test]
fn test_read_pattern() {
let example = " * comment1
*comment2
1: 00000 00000
2: 01010 11111\t11111
3:
:00000
*comment 3
5: 00000
00110";
let patterns = super::read_patterns(example.as_bytes()).unwrap();
assert_eq!(patterns.len(), 6);
assert_eq!(
patterns[0],
vec![
vec![false, false, false, false, false],
vec![false, false, false, false, false]
]
);
assert_eq!(
patterns[1],
vec![
vec![false, true, false, true, false],
vec![true, true, true, true, true],
vec![true, true, true, true, true]
]
);
assert_eq!(patterns[2], Vec::<Vec<bool>>::new());
assert_eq!(patterns[3], vec![vec![false, false, false, false, false],]);
assert_eq!(patterns[4], vec![vec![false, false, false, false, false],]);
assert_eq!(patterns[5], vec![vec![false, false, true, true, false],]);
}
#[test]
fn test_write_pattern() {
use std::io::BufWriter;
let example = vec![
vec![vec![false, true], vec![true, false]],
vec![vec![true, true]],
];
let mut buf = BufWriter::new(Vec::new());
super::write_patterns(&mut buf, &example);
let s = String::from_utf8(buf.into_inner().unwrap()).unwrap();
assert_eq!(
s,
"* Test pattern file
* generated by quaigh
1: 01 10
2: 11
"
);
}
}