noodles_sam/io/
indexed_reader.rs

1//! Indexed SAM reader.
2
3mod builder;
4
5use std::io::{self, Read, Seek};
6
7use noodles_bgzf as bgzf;
8use noodles_core::Region;
9use noodles_csi::BinningIndex;
10
11pub use self::builder::Builder;
12use super::{reader::RecordBufs, Reader};
13use crate::{alignment::RecordBuf, Header, Record};
14
15/// An indexed SAM reader.
16pub struct IndexedReader<R> {
17    inner: Reader<bgzf::Reader<R>>,
18    index: Box<dyn BinningIndex>,
19}
20
21impl<R> IndexedReader<R> {
22    /// Returns a reference to the underlying reader.
23    pub fn get_ref(&self) -> &bgzf::Reader<R> {
24        self.inner.get_ref()
25    }
26
27    /// Returns a mutable reference to the underlying reader.
28    pub fn get_mut(&mut self) -> &mut bgzf::Reader<R> {
29        self.inner.get_mut()
30    }
31
32    /// Returns the underlying reader.
33    pub fn into_inner(self) -> bgzf::Reader<R> {
34        self.inner.into_inner()
35    }
36}
37
38impl<R> IndexedReader<R>
39where
40    R: Read,
41{
42    /// Creates an indexed SAM reader.
43    pub fn new<I>(inner: R, index: I) -> Self
44    where
45        I: BinningIndex + 'static,
46    {
47        Self {
48            inner: Reader::new(bgzf::Reader::new(inner)),
49            index: Box::new(index),
50        }
51    }
52
53    /// Reads the SAM header.
54    pub fn read_header(&mut self) -> io::Result<Header> {
55        self.inner.read_header()
56    }
57
58    /// Reads a record into an alignment record buffer.
59    pub fn read_record_buf(
60        &mut self,
61        header: &Header,
62        record: &mut RecordBuf,
63    ) -> io::Result<usize> {
64        self.inner.read_record_buf(header, record)
65    }
66
67    /// Returns an iterator over alignment record buffers starting from the current stream
68    /// position.
69    pub fn record_bufs<'a>(&'a mut self, header: &'a Header) -> RecordBufs<'a, bgzf::Reader<R>> {
70        self.inner.record_bufs(header)
71    }
72
73    /// Reads a record.
74    pub fn read_record(&mut self, record: &mut Record) -> io::Result<usize> {
75        self.inner.read_record(record)
76    }
77
78    /// Returns an iterator over records.
79    pub fn records(&mut self) -> impl Iterator<Item = io::Result<Record>> + '_ {
80        self.inner.records()
81    }
82
83    /// Returns the associated index.
84    pub fn index(&self) -> &dyn BinningIndex {
85        &self.index
86    }
87}
88
89impl<R> IndexedReader<R>
90where
91    R: Read + Seek,
92{
93    /// Returns an iterator over records that intersect the given region.
94    pub fn query<'a>(
95        &'a mut self,
96        header: &'a Header,
97        region: &Region,
98    ) -> io::Result<impl Iterator<Item = io::Result<Record>> + 'a> {
99        self.inner.query(header, &self.index, region)
100    }
101
102    /// Returns an iterator of unmapped records after querying for the unmapped region.
103    pub fn query_unmapped(&mut self) -> io::Result<impl Iterator<Item = io::Result<Record>> + '_> {
104        self.inner.query_unmapped(&self.index)
105    }
106}