use std::io::Write;
use crate::{Block, ChainError, OwnedChain, OwnedChainHeader, Strand};
pub fn write_chain_dense<W: Write>(writer: &mut W, chain: &OwnedChain) -> Result<(), ChainError> {
write_chain_header(writer, chain)?;
write_dense_blocks(writer, &chain.blocks)
}
pub fn write_chain_header<W, C>(writer: &mut W, chain: &C) -> Result<(), ChainError>
where
W: Write,
C: ChainLike,
{
write!(writer, "chain {} ", chain.score())?;
writer.write_all(chain.reference_name())?;
write!(
writer,
" {} {} {} {} ",
chain.reference_size(),
strand_to_byte(chain.reference_strand()) as char,
chain.reference_start(),
chain.reference_end()
)?;
writer.write_all(chain.query_name())?;
writeln!(
writer,
" {} {} {} {} {}",
chain.query_size(),
strand_to_byte(chain.query_strand()) as char,
chain.query_start(),
chain.query_end(),
chain.id()
)?;
Ok(())
}
pub fn write_dense_blocks<W: Write>(writer: &mut W, blocks: &[Block]) -> Result<(), ChainError> {
for (index, block) in blocks.iter().enumerate() {
write!(writer, "{}", block.size)?;
if index + 1 < blocks.len() {
write!(writer, "\t{}\t{}", block.gap_reference, block.gap_query)?;
}
writer.write_all(b"\n")?;
}
writer.write_all(b"\n")?;
Ok(())
}
pub trait ChainLike {
fn score(&self) -> i64;
fn reference_name(&self) -> &[u8];
fn reference_size(&self) -> u32;
fn reference_strand(&self) -> Strand;
fn reference_start(&self) -> u32;
fn reference_end(&self) -> u32;
fn query_name(&self) -> &[u8];
fn query_size(&self) -> u32;
fn query_strand(&self) -> Strand;
fn query_start(&self) -> u32;
fn query_end(&self) -> u32;
fn id(&self) -> u64;
}
impl ChainLike for OwnedChain {
fn score(&self) -> i64 {
self.score
}
fn reference_name(&self) -> &[u8] {
&self.reference_name
}
fn reference_size(&self) -> u32 {
self.reference_size
}
fn reference_strand(&self) -> Strand {
self.reference_strand
}
fn reference_start(&self) -> u32 {
self.reference_start
}
fn reference_end(&self) -> u32 {
self.reference_end
}
fn query_name(&self) -> &[u8] {
&self.query_name
}
fn query_size(&self) -> u32 {
self.query_size
}
fn query_strand(&self) -> Strand {
self.query_strand
}
fn query_start(&self) -> u32 {
self.query_start
}
fn query_end(&self) -> u32 {
self.query_end
}
fn id(&self) -> u64 {
self.id
}
}
impl ChainLike for OwnedChainHeader {
fn score(&self) -> i64 {
self.score
}
fn reference_name(&self) -> &[u8] {
&self.reference_name
}
fn reference_size(&self) -> u32 {
self.reference_size
}
fn reference_strand(&self) -> Strand {
self.reference_strand
}
fn reference_start(&self) -> u32 {
self.reference_start
}
fn reference_end(&self) -> u32 {
self.reference_end
}
fn query_name(&self) -> &[u8] {
&self.query_name
}
fn query_size(&self) -> u32 {
self.query_size
}
fn query_strand(&self) -> Strand {
self.query_strand
}
fn query_start(&self) -> u32 {
self.query_start
}
fn query_end(&self) -> u32 {
self.query_end
}
fn id(&self) -> u64 {
self.id
}
}
fn strand_to_byte(strand: Strand) -> u8 {
match strand {
Strand::Plus => b'+',
Strand::Minus => b'-',
}
}