use std::{fs::File, io, sync::atomic::AtomicU64};
use anyhow::Result;
use clap::Parser;
use paraseq::fastx::RefRecord;
use paraseq::{fastx, prelude::*, ProcessError};
type BoxedReader = Box<dyn io::Read + Send>;
#[derive(Parser)]
struct Cli {
input_file: Option<String>,
#[clap(short = 'T', default_value = "1")]
num_threads: usize,
#[clap(short = 'B', default_value = "10")]
batch_size: usize,
}
impl Cli {
pub fn input_handle(&self) -> Result<BoxedReader> {
if let Some(path) = &self.input_file {
let file = File::open(path)?;
Ok(Box::new(file))
} else {
Ok(Box::new(io::stdin()))
}
}
}
fn main() -> Result<(), ProcessError> {
let args = Cli::parse();
let input_handle = args.input_handle()?;
let byte_sum = AtomicU64::new(0);
let num_records = AtomicU64::new(0);
let byte_sum_ref = &byte_sum;
let num_records_ref = &num_records;
let mut processor = |batch: &mut dyn Iterator<Item = RefRecord>| {
let mut local_byte_sum = 0u64;
let mut local_num_records = 0u64;
for record in batch {
for _ in 0..100 {
record
.seq()
.iter()
.for_each(|b| local_byte_sum += u64::from(*b));
}
local_num_records += 1;
}
byte_sum_ref.fetch_add(local_byte_sum, std::sync::atomic::Ordering::Relaxed);
num_records_ref.fetch_add(local_num_records, std::sync::atomic::Ordering::Relaxed);
Ok(())
};
let reader = fastx::Reader::new_with_batch_size(input_handle, args.batch_size)?;
reader.process_parallel(&mut processor, args.num_threads)?;
println!("num_records: {}", num_records.into_inner());
println!("byte_sum: {}", byte_sum.into_inner());
Ok(())
}