From 7bd2b6e82357970dd0331645c8d5e7bf9795235c Mon Sep 17 00:00:00 2001 From: Michael Macias Date: Tue, 14 May 2024 13:26:31 -0500 Subject: [PATCH] bam/record/sequence: Implement Debug This formats the sequence as a string rather than a list of encoded bytes. --- noodles-bam/src/record/sequence.rs | 49 ++++++++++++++++++++++++- noodles-bam/src/record/sequence/iter.rs | 2 +- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/noodles-bam/src/record/sequence.rs b/noodles-bam/src/record/sequence.rs index 90dd63ad3..8b2f69807 100644 --- a/noodles-bam/src/record/sequence.rs +++ b/noodles-bam/src/record/sequence.rs @@ -1,11 +1,13 @@ mod iter; +use std::fmt::{self, Write}; + use noodles_sam as sam; use self::iter::Iter; /// A BAM record sequence. -#[derive(Debug, Eq, PartialEq)] +#[derive(Eq, PartialEq)] pub struct Sequence<'a> { src: &'a [u8], base_count: usize, @@ -54,8 +56,53 @@ impl<'a> AsRef<[u8]> for Sequence<'a> { } } +impl<'a> fmt::Debug for Sequence<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + struct BasesFormat<'a>(&'a [u8], usize); + + impl<'a> fmt::Debug for BasesFormat<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use self::iter::decoded_bases; + + f.write_char('"')?; + + let BasesFormat(src, base_count) = *self; + + for b in src.iter().copied().flat_map(decoded_bases).take(base_count) { + f.write_char(char::from(b))?; + } + + f.write_char('"')?; + + Ok(()) + } + } + + f.debug_tuple("Sequence") + .field(&BasesFormat(self.src, self.base_count)) + .finish() + } +} + impl<'a> From> for sam::alignment::record_buf::Sequence { fn from(sequence: Sequence<'a>) -> Self { Self::from(sequence.as_ref().to_vec()) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_debug_fmt() { + let sequence = Sequence::new(&[], 0); + assert_eq!(format!("{sequence:?}"), r#"Sequence("")"#); + + let sequence = Sequence::new(&[0x12, 0x40], 3); + assert_eq!(format!("{sequence:?}"), r#"Sequence("ACG")"#); + + let sequence = Sequence::new(&[0x12, 0x48], 4); + assert_eq!(format!("{sequence:?}"), r#"Sequence("ACGT")"#); + } +} diff --git a/noodles-bam/src/record/sequence/iter.rs b/noodles-bam/src/record/sequence/iter.rs index f640d3849..e6c3fda31 100644 --- a/noodles-bam/src/record/sequence/iter.rs +++ b/noodles-bam/src/record/sequence/iter.rs @@ -68,7 +68,7 @@ impl<'a> ExactSizeIterator for Iter<'a> {} impl<'a> FusedIterator for Iter<'a> {} -fn decoded_bases(n: u8) -> array::IntoIter { +pub(super) fn decoded_bases(n: u8) -> array::IntoIter { [decode_base(n >> 4), decode_base(n)].into_iter() }