use anyhow::Result;
use noodles::sam::Header;
use crate::progress::ProgressLogger;
use crate::sam::alignment_reader::AlignmentReader;
use crate::sam::riker_record::{RikerRecord, RikerRecordRequirements};
pub trait Collector: Send {
fn initialize(&mut self, header: &Header) -> Result<()>;
fn accept(&mut self, record: &RikerRecord, header: &Header) -> Result<()>;
fn accept_multiple(&mut self, records: &[RikerRecord], header: &Header) -> Result<()> {
for record in records {
self.accept(record, header)?;
}
Ok(())
}
fn finish(&mut self) -> Result<()>;
fn name(&self) -> &'static str;
fn field_needs(&self) -> RikerRecordRequirements;
}
pub fn drive_collector_single_threaded(
reader: &mut AlignmentReader,
collector: &mut dyn Collector,
progress: &mut ProgressLogger,
) -> Result<()> {
let header = reader.header().clone();
if let Err(e) = collector.initialize(&header) {
let _ = collector.finish();
return Err(e);
}
let read_result = drive_records(reader, collector, progress, &header);
progress.finish();
let finish_result = collector.finish();
read_result?;
finish_result
}
fn drive_records(
reader: &mut AlignmentReader,
collector: &mut dyn Collector,
progress: &mut ProgressLogger,
header: &Header,
) -> Result<()> {
let requirements = collector.field_needs();
let mut record = reader.empty_record();
while reader.fill_record(&requirements, &mut record)? {
progress.record_with(&record, header);
collector.accept(&record, header)?;
}
Ok(())
}