use std::path::PathBuf;
use anyhow::Context;
use futures::TryStreamExt;
use noodles::bam::bai;
use noodles::sam;
use tokio::io::{self, AsyncWriteExt};
use crate::utils::formats::bam::ParsedAsyncBAMFile;
use crate::utils::formats::utils::IndexCheck;
use crate::view::command::Mode;
pub async fn view(src: PathBuf, query: Option<String>, mode: Mode) -> anyhow::Result<()> {
let ParsedAsyncBAMFile {
mut reader,
header,
index_path: bai_path,
..
} = crate::utils::formats::bam::open_and_parse_async(&src, IndexCheck::HeaderOnly).await?;
let mut handle = io::stdout();
if mode == Mode::Full || mode == Mode::HeaderOnly {
handle
.write_all(header.raw.to_string().as_bytes())
.await
.with_context(|| "writing header to stream")?;
}
if mode == Mode::HeaderOnly {
return Ok(());
}
let mut writer = sam::AsyncWriter::new(handle);
if let Some(query) = query {
let index = bai::read(bai_path).with_context(|| "reading BAM index")?;
let region = query.parse().with_context(|| "parsing query")?;
let mut records = reader
.query(&header.parsed, &index, ®ion)
.with_context(|| "querying BAM file")?;
while let Some(record) = records.try_next().await? {
writer
.write_alignment_record(&header.parsed, &record)
.await?;
}
} else {
let mut records = reader.records(&header.parsed);
while let Some(record) = records.try_next().await? {
writer
.write_alignment_record(&header.parsed, &record)
.await?;
}
}
Ok(())
}