use anyhow::{Error, Result};
use grep_cli::stdout;
use gzp::{BgzfSyncReader, Compression, ZBuilder, deflate::Bgzf};
use lazy_static::lazy_static;
use log::{error, warn};
use std::{
ffi::OsStr,
fs::File,
io::{self, BufReader, BufWriter, Read, Write},
path::Path,
};
use termcolor::ColorChoice;
pub fn set_rayon_global_pools_size(size: usize) -> Result<()> {
let cpus = determine_allowed_cpus(size)?;
rayon::ThreadPoolBuilder::new()
.num_threads(cpus)
.build_global()?;
Ok(())
}
#[inline]
pub fn is_broken_pipe(err: &Error) -> bool {
if let Some(io_err) = err.root_cause().downcast_ref::<io::Error>()
&& io_err.kind() == io::ErrorKind::BrokenPipe
{
return true;
}
false
}
pub fn determine_allowed_cpus(desired: usize) -> Result<usize> {
if desired == 0 {
error!("Must select > 0 threads");
Err(Error::msg("Too few threads selected. Min 4"))
} else if desired > num_cpus::get() {
let cpus = num_cpus::get();
warn!("Specified more threads than are available, using {}", cpus);
Ok(cpus)
} else {
Ok(desired)
}
}
pub fn is_bgzipped<P: AsRef<Path>>(path: P) -> bool {
let ext = path.as_ref().extension().unwrap_or_else(|| OsStr::new(""));
ext == "gz" || ext == "gzip" || ext == "bgzf"
}
pub fn get_reader<P: AsRef<Path>>(
path: &Option<P>,
has_headers: bool,
bgzipped: bool,
) -> Result<csv::Reader<Box<dyn Read>>> {
let raw_reader: Box<dyn Read> = match &path {
Some(path) if path.as_ref().to_str().unwrap() != "-" => {
let reader = BufReader::new(File::open(path)?);
if bgzipped {
Box::new(BgzfSyncReader::new(reader))
} else {
Box::new(reader)
}
}
_ => {
let reader = std::io::stdin();
if bgzipped {
Box::new(BgzfSyncReader::new(reader))
} else {
Box::new(reader)
}
}
};
Ok(csv::ReaderBuilder::new()
.delimiter(b'\t')
.has_headers(has_headers)
.from_reader(raw_reader))
}
pub fn get_writer<P: AsRef<Path>>(
path: &Option<P>,
bgzipped: bool,
write_headers: bool,
threads: usize,
compression_level: u32,
) -> Result<csv::Writer<Box<dyn Write>>> {
let raw_writer: Box<dyn Write> = match &path {
Some(path) if path.as_ref().to_str().unwrap() != "-" => {
let writer = BufWriter::new(File::create(path)?);
if bgzipped {
Box::new(
ZBuilder::<Bgzf, _>::new()
.num_threads(threads)
.compression_level(Compression::new(compression_level))
.from_writer(writer),
)
} else {
Box::new(writer)
}
}
_ => {
let writer = stdout(ColorChoice::Never);
if bgzipped {
Box::new(
ZBuilder::<Bgzf, _>::new()
.num_threads(threads)
.compression_level(Compression::new(compression_level))
.from_writer(writer),
)
} else {
Box::new(writer)
}
}
};
Ok(csv::WriterBuilder::new()
.delimiter(b'\t')
.has_headers(write_headers)
.from_writer(raw_writer))
}
lazy_static! {
pub static ref NUM_CPU: String = num_cpus::get().to_string();
}