noodles_sam/io/writer/
record.rsmod cigar;
mod data;
mod flags;
mod mapping_quality;
mod name;
mod position;
mod quality_scores;
mod reference_sequence_name;
mod sequence;
mod template_length;
use std::io::{self, Write};
pub use self::cigar::write_cigar;
use self::{
data::write_data,
flags::write_flags,
mapping_quality::write_mapping_quality,
name::write_name,
position::write_position,
quality_scores::write_quality_scores,
reference_sequence_name::{write_mate_reference_sequence_name, write_reference_sequence_name},
sequence::write_sequence,
template_length::write_template_length,
};
use crate::{alignment::Record, Header};
const MISSING: u8 = b'*';
pub(crate) fn write_record<W, R>(writer: &mut W, header: &Header, record: &R) -> io::Result<()>
where
W: Write,
R: Record + ?Sized,
{
const DELIMITER: &[u8] = b"\t";
write_name(writer, record.name())?;
writer.write_all(DELIMITER)?;
let flags = record.flags()?;
write_flags(writer, flags)?;
writer.write_all(DELIMITER)?;
let reference_sequence_name = record
.reference_sequence(header)
.transpose()?
.map(|(name, _)| name.as_ref());
write_reference_sequence_name(writer, reference_sequence_name)?;
writer.write_all(DELIMITER)?;
let alignment_start = record.alignment_start().transpose()?;
write_position(writer, alignment_start)?;
writer.write_all(DELIMITER)?;
let mapping_quality = record.mapping_quality().transpose()?;
write_mapping_quality(writer, mapping_quality)?;
let cigar = record.cigar();
writer.write_all(DELIMITER)?;
write_cigar(writer, &cigar)?;
writer.write_all(DELIMITER)?;
let mate_reference_sequence_name = record
.mate_reference_sequence(header)
.transpose()?
.map(|(name, _)| name.as_ref());
write_mate_reference_sequence_name(
writer,
reference_sequence_name,
mate_reference_sequence_name,
)?;
writer.write_all(DELIMITER)?;
let mate_alignment_start = record.mate_alignment_start().transpose()?;
write_position(writer, mate_alignment_start)?;
writer.write_all(DELIMITER)?;
let template_length = record.template_length()?;
write_template_length(writer, template_length)?;
let sequence = record.sequence();
let base_count = sequence.len();
writer.write_all(DELIMITER)?;
let read_length = cigar.read_length()?;
write_sequence(writer, read_length, sequence)?;
writer.write_all(DELIMITER)?;
write_quality_scores(writer, base_count, record.quality_scores())?;
write_data(writer, record.data())?;
writeln!(writer)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::alignment::RecordBuf;
#[test]
fn test_write_record_with_data() -> io::Result<()> {
use crate::alignment::{record::data::field::Tag, record_buf::data::field::Value};
let mut buf = Vec::new();
let header = Header::default();
let data = [(Tag::READ_GROUP, Value::from("rg0"))]
.into_iter()
.collect();
let record = RecordBuf::builder().set_data(data).build();
write_record(&mut buf, &header, &record)?;
let expected = b"*\t4\t*\t0\t255\t*\t*\t0\t0\t*\t*\tRG:Z:rg0\n";
assert_eq!(buf, expected);
Ok(())
}
}