use crate::bam::{self, BamReader, BamRecord, EntriesRequest, SamHeader};
use crate::cram::{self, CramReader};
use crate::error::{Error, Result};
use crate::genomic::ChrMap;
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum Alignments {
Bam(BamReader),
Cram(CramReader),
}
impl Alignments {
pub fn kind(&self) -> &'static str {
match self {
Self::Bam(_) => "bam",
Self::Cram(_) => "cram",
}
}
pub fn header(&self) -> &SamHeader {
match self {
Self::Bam(reader) => reader.header(),
Self::Cram(reader) => reader.header(),
}
}
pub fn chr_sizes(&self) -> &ChrMap {
match self {
Self::Bam(reader) => reader.chr_sizes(),
Self::Cram(reader) => reader.chr_sizes(),
}
}
pub fn is_indexed(&self) -> bool {
match self {
Self::Bam(reader) => reader.is_indexed(),
Self::Cram(reader) => reader.is_indexed(),
}
}
pub fn index_error(&self) -> &str {
match self {
Self::Bam(reader) => reader.index_error(),
Self::Cram(reader) => reader.index_error(),
}
}
pub fn is_closed(&self) -> bool {
match self {
Self::Bam(reader) => reader.is_closed(),
Self::Cram(reader) => reader.is_closed(),
}
}
pub fn path(&self) -> &str {
match self {
Self::Bam(reader) => reader.path(),
Self::Cram(reader) => reader.path(),
}
}
pub fn parallel(&self) -> usize {
match self {
Self::Bam(reader) => reader.parallel(),
Self::Cram(reader) => reader.parallel(),
}
}
pub fn close(&mut self) {
match self {
Self::Bam(reader) => reader.close(),
Self::Cram(reader) => reader.close(),
}
}
pub fn version(&self) -> Option<(u8, u8)> {
match self {
Self::Bam(_) => None,
Self::Cram(reader) => Some(reader.version()),
}
}
pub fn reference_path(&self) -> Option<&str> {
match self {
Self::Bam(_) => None,
Self::Cram(reader) => reader.reference_path(),
}
}
pub fn reference_error(&self) -> &str {
match self {
Self::Bam(_) => "",
Self::Cram(reader) => reader.reference_error(),
}
}
pub fn read_entries(&self, req: &EntriesRequest) -> Result<Vec<Vec<BamRecord>>> {
match self {
Self::Bam(reader) => reader.read_entries(req),
Self::Cram(reader) => reader.read_entries(req),
}
}
pub fn read_all_entries(&self, req: &EntriesRequest) -> Result<Vec<BamRecord>> {
match self {
Self::Bam(reader) => reader.read_all_entries(req),
Self::Cram(reader) => reader.read_all_entries(req),
}
}
}
#[derive(Debug)]
pub enum AlignmentWalk {
Bam(bam::LocusWalk),
Cram(cram::LocusWalk),
}
impl AlignmentWalk {
pub fn plan(reader: &Alignments, req: &EntriesRequest) -> Result<Self> {
Ok(match reader {
Alignments::Bam(reader) => Self::Bam(bam::LocusWalk::plan(reader, req)?),
Alignments::Cram(reader) => Self::Cram(cram::LocusWalk::plan(reader, req)?),
})
}
pub fn plan_windows(reader: &Alignments, req: &EntriesRequest, span: i64) -> Result<Self> {
Ok(match reader {
Alignments::Bam(reader) => Self::Bam(bam::LocusWalk::plan_windows(reader, req, span)?),
Alignments::Cram(reader) => {
Self::Cram(cram::LocusWalk::plan_windows(reader, req, span)?)
}
})
}
pub fn restarted(&self) -> Self {
match self {
Self::Bam(walk) => Self::Bam(walk.restarted()),
Self::Cram(walk) => Self::Cram(walk.restarted()),
}
}
pub fn len(&self) -> usize {
match self {
Self::Bam(walk) => walk.len(),
Self::Cram(walk) => walk.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn order(&self) -> &[usize] {
match self {
Self::Bam(walk) => walk.order(),
Self::Cram(walk) => walk.order(),
}
}
pub fn next_window(&mut self, reader: &Alignments) -> Option<Result<Vec<BamRecord>>> {
match (self, reader) {
(Self::Bam(walk), Alignments::Bam(reader)) => walk.next_window(reader),
(Self::Cram(walk), Alignments::Cram(reader)) => walk.next_window(reader),
_ => Some(Err(Error::invalid(
"this walk was planned against a reader of the other format",
))),
}
}
}