Skip to main content

fastq_chunk_sink/
fastq_chunk_sink.rs

1use std::io;
2
3use dino_seq::{
4    FastqChunkConfig, FastqChunkSinkExt, FastqReader, FastqRecordSink, FastqVisitRecord, Result,
5};
6
7#[derive(Debug)]
8struct OwnedRead {
9    name: Vec<u8>,
10    seq: Vec<u8>,
11    qual: Vec<u8>,
12}
13
14#[derive(Debug, Default)]
15struct ReadBuffer {
16    reads: Vec<OwnedRead>,
17    bases: u64,
18}
19
20impl FastqRecordSink for ReadBuffer {
21    fn record(&mut self, record: FastqVisitRecord<'_>) -> Result<()> {
22        self.bases += record.seq().len() as u64;
23        self.reads.push(OwnedRead {
24            name: record.name().to_vec(),
25            seq: record.seq().to_vec(),
26            qual: record.qual().to_vec(),
27        });
28        Ok(())
29    }
30}
31
32impl FastqChunkSinkExt for ReadBuffer {
33    fn reserve_records(&mut self, records: usize) {
34        self.reads.reserve(records);
35    }
36}
37
38impl ReadBuffer {
39    fn clear(&mut self) {
40        self.reads.clear();
41        self.bases = 0;
42    }
43}
44
45fn main() -> Result<()> {
46    let stdin = io::stdin();
47    let mut reader = FastqReader::new(stdin.lock());
48    let config = FastqChunkConfig::new(10_000_000).min_records(40_000);
49    let mut sink = ReadBuffer::default();
50
51    sink.reserve_records(config.estimated_records(150));
52    while let Some(stats) = reader.next_chunk_with_sink(config, &mut sink)? {
53        let checksum: usize = sink
54            .reads
55            .iter()
56            .map(|read| read.name.len() ^ read.seq.len() ^ read.qual.len())
57            .sum();
58        eprintln!(
59            "chunk first_record={} records={} bases={} checksum={}",
60            stats.first_record_index(),
61            stats.records(),
62            stats.bases(),
63            checksum
64        );
65
66        // Downstream tools typically hand `sink.reads` to alignment or another
67        // processing stage here, then reuse the allocation for the next chunk.
68        sink.clear();
69        sink.reserve_records(config.estimated_records(150));
70    }
71
72    Ok(())
73}