use anyhow::{Context, Result}; use itertools::{self, Itertools}; use std::{ fs::File, io::{BufRead, BufReader}, path::PathBuf, }; fn parse_single_line(l: String) -> Result<(f64, u32, u32)> { let mut splitted = l.split_whitespace(); let delay: f64 = splitted.next().context("No value found")?.parse()?; let high_count: u32 = splitted.next().context("No value found")?.parse()?; let low_count: u32 = splitted.next().context("No value found")?.parse()?; assert!(splitted.next().is_none()); Ok((delay, high_count, low_count)) } fn parse_counts(f: impl BufRead) -> Result { let delay = f .lines() .filter_map(|l| parse_single_line(l.ok()?).ok()) .tuple_windows() .find(|((_, high1, _), (_, high2, _))| *high1 < 500 && *high2 >= 500) .context("Failed to get rise edge")? .1 .0; Ok(delay) } /// Read clock scan file and get skew. pub fn parse_count_file(filename: PathBuf) -> Result { let buf_reader = BufReader::new( File::open(filename.clone()) .context(format!("Error opening file {}", filename.display()))?, ); parse_counts(buf_reader) } #[cfg(test)] mod test { use super::parse_counts; #[test] fn test_parse_counts1() { let file = " 0.1 0 1000 0.2 10 990 0.3 470 530 0.4 500 500 0.5 510 490 0.6 900 100 0.7 1000 0 " .as_bytes(); assert_eq!(parse_counts(file).unwrap(), 0.4); let file2 = " 0.1 0 1000 0.2 10 990 0.3 470 530 0.4 499 501 0.5 510 490 0.6 900 100 0.7 1000 0 " .as_bytes(); assert_eq!(parse_counts(file2).unwrap(), 0.5); let file3 = " 0.1 0 1000 0.2 10 990 0.3 470 530 0.4 501 499 0.5 510 490 0.6 900 100 0.7 1000 0 " .as_bytes(); assert_eq!(parse_counts(file3).unwrap(), 0.4); } }