use crate::Result;
use super::FastqVisitRecord;
pub trait FastqRecordSink {
fn record(&mut self, record: FastqVisitRecord<'_>) -> Result<()>;
}
impl<F> FastqRecordSink for F
where
F: for<'a> FnMut(FastqVisitRecord<'a>) -> Result<()>,
{
fn record(&mut self, record: FastqVisitRecord<'_>) -> Result<()> {
self(record)
}
}
pub trait FastqChunkSinkExt: FastqRecordSink {
fn reserve_records(&mut self, _records: usize) {}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FastqChunkConfig {
pub target_bases: u64,
pub min_records: usize,
pub max_bases: u64,
}
impl FastqChunkConfig {
pub fn new(target_bases: u64) -> Self {
Self {
target_bases,
min_records: 1,
max_bases: 0,
}
}
pub fn min_records(mut self, min_records: usize) -> Self {
self.min_records = min_records.max(1);
self
}
pub fn max_bases(mut self, max_bases: u64) -> Self {
self.max_bases = max_bases;
self
}
pub fn target_bases(self) -> u64 {
self.target_bases
}
pub fn min_records_value(self) -> usize {
self.min_records
}
pub fn max_bases_value(self) -> u64 {
self.max_bases
}
pub fn estimated_records(self, read_len: usize) -> usize {
let read_len = read_len.max(1) as u64;
let target = if self.max_bases != 0 {
self.max_bases
} else {
self.target_bases
};
if target == 0 {
return self.min_records.max(1);
}
target
.div_ceil(read_len)
.max(self.min_records.max(1) as u64)
.min(usize::MAX as u64) as usize
}
pub(crate) fn normalized(self) -> Self {
Self {
min_records: self.min_records.max(1),
..self
}
}
pub(crate) fn should_stop(self, records: u64, bases: u64) -> bool {
if self.max_bases != 0 && bases >= self.max_bases {
return true;
}
self.target_bases != 0 && bases >= self.target_bases && records >= self.min_records as u64
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FastqChunkStats {
pub first_record_index: u64,
pub records: u64,
pub bases: u64,
}
impl FastqChunkStats {
pub(crate) fn new(first_record_index: u64) -> Self {
Self {
first_record_index,
records: 0,
bases: 0,
}
}
pub fn first_record_index(self) -> u64 {
self.first_record_index
}
pub fn records(self) -> u64 {
self.records
}
pub fn bases(self) -> u64 {
self.bases
}
pub fn is_empty(self) -> bool {
self.records == 0
}
}