use std::path::PathBuf;
use anyhow::{Context, Result};
use clap::Args;
use serde::Serialize;
use crate::cli::RunContext;
use crate::io::reader::open_input;
use crate::output::{write, HumanDisplay, OutputFormat};
#[derive(Args, Debug)]
pub struct CountArgs {
pub input: PathBuf,
#[arg(long, conflicts_with = "tsv")]
pub json: bool,
#[arg(long, conflicts_with = "json")]
pub tsv: bool,
}
#[derive(Debug, Serialize)]
pub struct CountResult {
pub file: String,
pub reads: u64,
pub bases: u64,
}
pub fn run(args: CountArgs, _ctx: &RunContext) -> Result<()> {
let result = compute(&args)?;
let format = if args.json {
OutputFormat::Json
} else if args.tsv {
OutputFormat::Tsv
} else {
OutputFormat::auto()
};
write(&result, format)?;
Ok(())
}
fn compute(args: &CountArgs) -> Result<CountResult> {
let mut reader = open_input(&args.input).context("opening input")?;
let mut reads = 0u64;
let mut bases = 0u64;
while let Some(record) = reader.next_record().context("reading record")? {
reads += 1;
bases += record.len() as u64;
}
Ok(CountResult {
file: args.input.display().to_string(),
reads,
bases,
})
}
impl HumanDisplay for CountResult {
fn write_human(&self, w: &mut dyn std::io::Write) -> Result<()> {
writeln!(
w,
"{}\treads={}\tbases={}",
self.file, self.reads, self.bases
)?;
Ok(())
}
fn write_tsv(&self, w: &mut dyn std::io::Write) -> Result<()> {
writeln!(w, "file\treads\tbases")?;
writeln!(w, "{}\t{}\t{}", self.file, self.reads, self.bases)?;
Ok(())
}
}