1use crate::bam::{self, BamReader, BamRecord, EntriesRequest, SamHeader};
23use crate::cram::{self, CramReader};
24use crate::error::{Error, Result};
25use crate::genomic::ChrMap;
26
27#[allow(clippy::large_enum_variant)]
29#[derive(Debug)]
30pub enum Alignments {
31 Bam(BamReader),
32 Cram(CramReader),
33}
34
35impl Alignments {
36 pub fn kind(&self) -> &'static str {
38 match self {
39 Self::Bam(_) => "bam",
40 Self::Cram(_) => "cram",
41 }
42 }
43
44 pub fn header(&self) -> &SamHeader {
45 match self {
46 Self::Bam(reader) => reader.header(),
47 Self::Cram(reader) => reader.header(),
48 }
49 }
50
51 pub fn chr_sizes(&self) -> &ChrMap {
52 match self {
53 Self::Bam(reader) => reader.chr_sizes(),
54 Self::Cram(reader) => reader.chr_sizes(),
55 }
56 }
57
58 pub fn is_indexed(&self) -> bool {
59 match self {
60 Self::Bam(reader) => reader.is_indexed(),
61 Self::Cram(reader) => reader.is_indexed(),
62 }
63 }
64
65 pub fn index_error(&self) -> &str {
66 match self {
67 Self::Bam(reader) => reader.index_error(),
68 Self::Cram(reader) => reader.index_error(),
69 }
70 }
71
72 pub fn is_closed(&self) -> bool {
73 match self {
74 Self::Bam(reader) => reader.is_closed(),
75 Self::Cram(reader) => reader.is_closed(),
76 }
77 }
78
79 pub fn path(&self) -> &str {
80 match self {
81 Self::Bam(reader) => reader.path(),
82 Self::Cram(reader) => reader.path(),
83 }
84 }
85
86 pub fn parallel(&self) -> usize {
87 match self {
88 Self::Bam(reader) => reader.parallel(),
89 Self::Cram(reader) => reader.parallel(),
90 }
91 }
92
93 pub fn close(&mut self) {
94 match self {
95 Self::Bam(reader) => reader.close(),
96 Self::Cram(reader) => reader.close(),
97 }
98 }
99
100 pub fn version(&self) -> Option<(u8, u8)> {
102 match self {
103 Self::Bam(_) => None,
104 Self::Cram(reader) => Some(reader.version()),
105 }
106 }
107
108 pub fn reference_path(&self) -> Option<&str> {
110 match self {
111 Self::Bam(_) => None,
112 Self::Cram(reader) => reader.reference_path(),
113 }
114 }
115
116 pub fn reference_error(&self) -> &str {
118 match self {
119 Self::Bam(_) => "",
120 Self::Cram(reader) => reader.reference_error(),
121 }
122 }
123
124 pub fn read_entries(&self, req: &EntriesRequest) -> Result<Vec<Vec<BamRecord>>> {
125 match self {
126 Self::Bam(reader) => reader.read_entries(req),
127 Self::Cram(reader) => reader.read_entries(req),
128 }
129 }
130
131 pub fn read_all_entries(&self, req: &EntriesRequest) -> Result<Vec<BamRecord>> {
132 match self {
133 Self::Bam(reader) => reader.read_all_entries(req),
134 Self::Cram(reader) => reader.read_all_entries(req),
135 }
136 }
137}
138
139#[derive(Debug)]
141pub enum AlignmentWalk {
142 Bam(bam::LocusWalk),
143 Cram(cram::LocusWalk),
144}
145
146impl AlignmentWalk {
147 pub fn plan(reader: &Alignments, req: &EntriesRequest) -> Result<Self> {
149 Ok(match reader {
150 Alignments::Bam(reader) => Self::Bam(bam::LocusWalk::plan(reader, req)?),
151 Alignments::Cram(reader) => Self::Cram(cram::LocusWalk::plan(reader, req)?),
152 })
153 }
154
155 pub fn plan_windows(reader: &Alignments, req: &EntriesRequest, span: i64) -> Result<Self> {
157 Ok(match reader {
158 Alignments::Bam(reader) => Self::Bam(bam::LocusWalk::plan_windows(reader, req, span)?),
159 Alignments::Cram(reader) => {
160 Self::Cram(cram::LocusWalk::plan_windows(reader, req, span)?)
161 }
162 })
163 }
164
165 pub fn restarted(&self) -> Self {
167 match self {
168 Self::Bam(walk) => Self::Bam(walk.restarted()),
169 Self::Cram(walk) => Self::Cram(walk.restarted()),
170 }
171 }
172
173 pub fn len(&self) -> usize {
174 match self {
175 Self::Bam(walk) => walk.len(),
176 Self::Cram(walk) => walk.len(),
177 }
178 }
179
180 pub fn is_empty(&self) -> bool {
181 self.len() == 0
182 }
183
184 pub fn order(&self) -> &[usize] {
185 match self {
186 Self::Bam(walk) => walk.order(),
187 Self::Cram(walk) => walk.order(),
188 }
189 }
190
191 pub fn next_window(&mut self, reader: &Alignments) -> Option<Result<Vec<BamRecord>>> {
197 match (self, reader) {
198 (Self::Bam(walk), Alignments::Bam(reader)) => walk.next_window(reader),
199 (Self::Cram(walk), Alignments::Cram(reader)) => walk.next_window(reader),
200 _ => Some(Err(Error::invalid(
201 "this walk was planned against a reader of the other format",
202 ))),
203 }
204 }
205}