noodles_cram/io/reader/
records.rs1use std::{
2 io::{self, Read},
3 vec,
4};
5
6use noodles_sam as sam;
7
8use super::{Container, Reader};
9
10pub struct Records<'a, R>
14where
15 R: Read,
16{
17 reader: &'a mut Reader<R>,
18 header: &'a sam::Header,
19 container: Container,
20 records: vec::IntoIter<sam::alignment::RecordBuf>,
21}
22
23impl<'a, R> Records<'a, R>
24where
25 R: Read,
26{
27 pub(crate) fn new(reader: &'a mut Reader<R>, header: &'a sam::Header) -> Self {
28 Self {
29 reader,
30 header,
31 container: Container::default(),
32 records: Vec::new().into_iter(),
33 }
34 }
35
36 fn read_container_records(&mut self) -> io::Result<bool> {
37 if self.reader.read_container(&mut self.container)? == 0 {
38 return Ok(true);
39 }
40
41 let compression_header = self.container.compression_header()?;
42
43 self.records = self
44 .container
45 .slices()
46 .map(|result| {
47 let slice = result?;
48
49 let (core_data_src, external_data_srcs) = slice.decode_blocks()?;
50
51 slice
52 .records(
53 self.reader.reference_sequence_repository.clone(),
54 self.header,
55 &compression_header,
56 &core_data_src,
57 &external_data_srcs,
58 )
59 .and_then(|records| {
60 records
61 .into_iter()
62 .map(|record| {
63 sam::alignment::RecordBuf::try_from_alignment_record(
64 self.header,
65 &record,
66 )
67 })
68 .collect::<io::Result<Vec<_>>>()
69 })
70 })
71 .collect::<Result<Vec<_>, _>>()?
72 .into_iter()
73 .flatten()
74 .collect::<Vec<_>>()
75 .into_iter();
76
77 Ok(false)
78 }
79}
80
81impl<R> Iterator for Records<'_, R>
82where
83 R: Read,
84{
85 type Item = io::Result<sam::alignment::RecordBuf>;
86
87 fn next(&mut self) -> Option<Self::Item> {
88 loop {
89 match self.records.next() {
90 Some(r) => return Some(Ok(r)),
91 None => match self.read_container_records() {
92 Ok(true) => return None,
93 Ok(false) => {}
94 Err(e) => return Some(Err(e)),
95 },
96 }
97 }
98 }
99}