#![doc(html_root_url = "https://docs.rs/runiq/1.2.1")]
pub mod filters;
mod options;
mod statistics;
use bytelines::ByteLinesReader;
use crate::filters::Filter;
use crate::options::Options;
use crate::statistics::Stats;
use std::env;
use std::fs::File;
use std::io::{self, BufReader, Read, Write};
const EOL: &[u8; 1] = &[b'\n'];
fn main() -> io::Result<()> {
let options = Options::from(&mut env::args_os());
let stdin = io::stdin();
let stdout = io::stdout();
let readers: Vec<Box<dyn Read>> = (&options.inputs)
.iter()
.map(|input| -> Box<dyn Read> {
match input.as_ref() {
"-" => Box::new(stdin.lock()),
any => Box::new(File::open(any).unwrap()),
}
})
.collect();
let mut filter: Box<dyn Filter> = options.filter.into();
let mut statistics = Stats::new();
let mut stdout = stdout.lock();
for reader in readers {
let mut lines = BufReader::new(reader).byte_lines();
while let Some(line) = lines.next() {
let input = line?;
if filter.detect(&input) {
if options.statistics {
statistics.add_unique();
} else if !options.inverted {
stdout.write_all(input)?;
stdout.write_all(EOL)?;
}
} else {
if options.statistics {
statistics.add_duplicate();
} else if options.inverted {
stdout.write_all(input)?;
stdout.write_all(EOL)?;
}
}
}
}
if options.statistics {
statistics.print();
}
stdout.flush()?;
Ok(())
}