use std::{fs::File, io::BufWriter};
use anyhow::Result;
use binseq::{BinseqWriterBuilder, write::Format};
use bitnuc::BitSize;
use clap::Parser;
type BoxedWriter = Box<dyn std::io::Write + Send>;
#[derive(Parser)]
struct Args {
#[clap(required = true)]
input: String,
#[clap(required = false)]
input2: Option<String>,
#[clap(short = 'o', long)]
output: Option<String>,
#[clap(short = 'p', long, default_value = "output")]
prefix: String,
#[clap(short = 'f', long)]
format: Option<Format>,
#[clap(short = 'Q', long)]
exclude_quality: bool,
#[clap(short = 'H', long)]
exclude_headers: bool,
#[clap(long, default_value_t = 0)]
compression_level: i32,
#[clap(long, default_value_t = 2)]
bitsize: u8,
#[clap(long, default_value_t = 128)]
blocksize: usize,
#[clap(short = 'T', long, default_value = "0")]
threads: usize,
}
impl Args {
fn format(&self) -> Format {
if let Some(format) = self.format {
format
} else {
if let Some(output) = &self.output {
match output.split(".").last() {
Some("bq") => Format::Bq,
Some("vbq") => Format::Vbq,
Some("cbq") => Format::Cbq,
_ => Format::default(),
}
} else {
Format::default()
}
}
}
fn bitsize(&self) -> BitSize {
match self.bitsize {
4 => BitSize::Four,
_ => BitSize::Two,
}
}
fn ohandle(&self) -> Result<BoxedWriter> {
let path = if let Some(output) = &self.output {
output.to_string()
} else {
format!("{}{}", &self.prefix, self.format().extension())
};
let ofile = File::create(path).map(BufWriter::new)?;
Ok(Box::new(ofile))
}
fn is_paired(&self) -> bool {
self.input2.is_some()
}
}
fn main() -> Result<()> {
let args = Args::parse();
let handle = args.ohandle()?;
let builder = BinseqWriterBuilder::new(args.format())
.bitsize(args.bitsize())
.block_size(args.blocksize * 1024)
.headers(!args.exclude_headers)
.quality(!args.exclude_quality)
.compression_level(args.compression_level)
.encode_fastx(handle);
if args.is_paired() {
builder.input_paired(&args.input, args.input2.as_ref().unwrap())
} else {
builder.input(&args.input)
}
.threads(args.threads)
.run()?;
Ok(())
}