1use std::fs::File;
2use std::io::{BufRead, BufReader, BufWriter, Write};
3use std::path::Path;
4
5use regex::Regex;
6use rsomics_common::{Result, RsomicsError};
7
8pub fn grep(input: &Path, pattern: &str, invert: bool, output: &mut dyn Write) -> Result<u64> {
9 let re =
10 Regex::new(pattern).map_err(|e| RsomicsError::InvalidInput(format!("bad regex: {e}")))?;
11 let file = File::open(input)
12 .map_err(|e| RsomicsError::InvalidInput(format!("{}: {e}", input.display())))?;
13 let reader = BufReader::new(file);
14 let mut out = BufWriter::with_capacity(64 * 1024, output);
15 let mut count: u64 = 0;
16
17 for line in reader.lines() {
18 let line = line.map_err(RsomicsError::Io)?;
19 if line.starts_with('#') {
20 writeln!(out, "{line}").map_err(RsomicsError::Io)?;
21 continue;
22 }
23 let matches = re.is_match(&line);
24 if matches != invert {
25 writeln!(out, "{line}").map_err(RsomicsError::Io)?;
26 count += 1;
27 }
28 }
29
30 out.flush().map_err(RsomicsError::Io)?;
31 Ok(count)
32}