noodles_cram/io/reader/
query.rs1use std::{
2 io::{self, Read, Seek, SeekFrom},
3 slice, vec,
4};
5
6use noodles_core::region::Interval;
7use noodles_sam as sam;
8
9use super::{Container, Reader};
10use crate::crai;
11
12pub struct Query<'a, R>
16where
17 R: Read + Seek,
18{
19 reader: &'a mut Reader<R>,
20
21 header: &'a sam::Header,
22
23 index: slice::Iter<'a, crai::Record>,
24
25 reference_sequence_id: usize,
26 interval: Interval,
27
28 records: vec::IntoIter<sam::alignment::RecordBuf>,
29}
30
31impl<'a, R> Query<'a, R>
32where
33 R: Read + Seek,
34{
35 pub(super) fn new(
36 reader: &'a mut Reader<R>,
37 header: &'a sam::Header,
38 index: &'a crai::Index,
39 reference_sequence_id: usize,
40 interval: Interval,
41 ) -> Self {
42 Self {
43 reader,
44
45 header,
46
47 index: index.iter(),
48
49 reference_sequence_id,
50 interval,
51
52 records: Vec::new().into_iter(),
53 }
54 }
55
56 fn read_next_container(&mut self) -> Option<io::Result<()>> {
57 let index_record = self.index.next()?;
58
59 if index_record.reference_sequence_id() != Some(self.reference_sequence_id) {
60 return Some(Ok(()));
61 }
62
63 if let Err(e) = self.reader.seek(SeekFrom::Start(index_record.offset())) {
64 return Some(Err(e));
65 }
66
67 let mut container = Container::default();
68
69 match self.reader.read_container(&mut container) {
70 Ok(0) => return None,
71 Ok(_) => {}
72 Err(e) => return Some(Err(e)),
73 };
74
75 let compression_header = match container.compression_header() {
76 Ok(compression_header) => compression_header,
77 Err(e) => return Some(Err(e)),
78 };
79
80 let records = container
81 .slices()
82 .map(|result| {
83 let slice = result?;
84
85 let (core_data_src, external_data_srcs) = slice.decode_blocks()?;
86
87 slice
88 .records(
89 self.reader.reference_sequence_repository.clone(),
90 self.header,
91 &compression_header,
92 &core_data_src,
93 &external_data_srcs,
94 )
95 .and_then(|records| {
96 records
97 .into_iter()
98 .map(|record| {
99 sam::alignment::RecordBuf::try_from_alignment_record(
100 self.header,
101 &record,
102 )
103 })
104 .collect::<io::Result<Vec<_>>>()
105 })
106 })
107 .collect::<Result<Vec<_>, _>>();
108
109 let records = match records {
110 Ok(records) => records,
111 Err(e) => return Some(Err(e)),
112 };
113
114 self.records = records
115 .into_iter()
116 .flatten()
117 .collect::<Vec<_>>()
118 .into_iter();
119
120 Some(Ok(()))
121 }
122}
123
124impl<R> Iterator for Query<'_, R>
125where
126 R: Read + Seek,
127{
128 type Item = io::Result<sam::alignment::RecordBuf>;
129
130 fn next(&mut self) -> Option<Self::Item> {
131 loop {
132 match self.records.next() {
133 Some(r) => {
134 if let (Some(start), Some(end)) = (r.alignment_start(), r.alignment_end()) {
135 let alignment_interval = (start..=end).into();
136
137 if self.interval.intersects(alignment_interval) {
138 return Some(Ok(r));
139 }
140 }
141 }
142 None => match self.read_next_container() {
143 Some(Ok(())) => {}
144 Some(Err(e)) => return Some(Err(e)),
145 None => return None,
146 },
147 }
148 }
149 }
150}