diff --git a/src/bam/ext.rs b/src/bam/ext.rs index c02ce1b5b..fdaa891bc 100644 --- a/src/bam/ext.rs +++ b/src/bam/ext.rs @@ -313,6 +313,64 @@ pub trait BamRecordExtensions { fn seq_len_from_cigar(&self, include_hard_clip: bool) -> usize; } +impl IterAlignedBlocks { + /// Create a new `IterAlignedBlocks` from its component parts. + /// + /// This allows constructing an iterator over aligned blocks without needing + /// access to a `BamRecordExtensions` instance. + /// + /// # Arguments + /// + /// * `pos` - The starting position on the reference sequence + /// * `cigar` - The CIGAR operations as a vector + /// + /// # Example + /// + /// ``` + /// use rust_htslib::bam::record::Cigar; + /// use rust_htslib::bam::ext::IterAlignedBlocks; + /// + /// let cigar = vec![Cigar::Match(10), Cigar::Del(5), Cigar::Match(20)]; + /// let iter = IterAlignedBlocks::new(100, cigar); + /// ``` + pub fn new(pos: i64, cigar: Vec) -> Self { + Self { + pos, + cigar_index: 0, + cigar, + } + } +} + +impl IterIntrons { + /// Create a new `IterIntrons` from its component parts. + /// + /// This allows constructing an iterator over introns without needing + /// access to a `BamRecordExtensions` instance. + /// + /// # Arguments + /// + /// * `pos` - The starting position on the reference sequence + /// * `cigar` - The CIGAR operations as a vector + /// + /// # Example + /// + /// ``` + /// use rust_htslib::bam::record::Cigar; + /// use rust_htslib::bam::ext::IterIntrons; + /// + /// let cigar = vec![Cigar::Match(10), Cigar::RefSkip(1000), Cigar::Match(20)]; + /// let iter = IterIntrons::new(100, cigar); + /// ``` + pub fn new(pos: i64, cigar: Vec) -> Self { + Self { + pos, + cigar_index: 0, + cigar, + } + } +} + impl BamRecordExtensions for bam::Record { fn aligned_blocks(&self) -> IterAlignedBlocks { IterAlignedBlocks { @@ -1022,6 +1080,26 @@ mod tests { assert_eq!(introns[1], [44589703, 44592034]); } + #[test] + fn test_iter_constructors() { + use crate::bam::ext::{IterAlignedBlocks, IterIntrons}; + + // Test IterAlignedBlocks constructor + let cigar = vec![Cigar::Match(10), Cigar::Del(5), Cigar::Match(20)]; + let iter = IterAlignedBlocks::new(100, cigar); + let blocks: Vec<_> = iter.collect(); + assert_eq!(blocks.len(), 2); + assert_eq!(blocks[0], [100, 110]); + assert_eq!(blocks[1], [115, 135]); + + // Test IterIntrons constructor + let cigar = vec![Cigar::Match(10), Cigar::RefSkip(1000), Cigar::Match(20)]; + let iter = IterIntrons::new(100, cigar); + let introns: Vec<_> = iter.collect(); + assert_eq!(introns.len(), 1); + assert_eq!(introns[0], [110, 1110]); + } + #[test] fn test_aligned_pairs() { let mut bam = bam::Reader::from_path("./test/test_spliced_reads.bam").unwrap(); diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 41fe6f134..474c6202c 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -1029,8 +1029,8 @@ impl Read for IndexedReader { impl Drop for IndexedReader { fn drop(&mut self) { unsafe { - if self.itr.is_some() { - htslib::hts_itr_destroy(self.itr.unwrap()); + if let Some(itr) = self.itr { + htslib::hts_itr_destroy(itr); } htslib::hts_close(self.htsfile); } diff --git a/src/bcf/buffer.rs b/src/bcf/buffer.rs index 130e39027..e54a86a54 100644 --- a/src/bcf/buffer.rs +++ b/src/bcf/buffer.rs @@ -107,18 +107,16 @@ impl RecordBuffer { } // move overflow from last fill into ringbuffer - if self.overflow.is_some() { - let pos = self.overflow.as_ref().unwrap().pos() as u64; + if let Some(overflow) = self.overflow.take() { + let pos = overflow.pos() as u64; if pos >= start { if pos <= end { - self.ringbuffer.push_back(self.overflow.take().unwrap()); + self.ringbuffer.push_back(overflow); added += 1; } else { + self.overflow = Some(overflow); return Ok((added, deleted)); } - } else { - // discard overflow - self.overflow.take(); } } diff --git a/src/tbx/mod.rs b/src/tbx/mod.rs index 5994c49e3..18ea00bba 100644 --- a/src/tbx/mod.rs +++ b/src/tbx/mod.rs @@ -316,8 +316,8 @@ impl Read for Reader { impl Drop for Reader { fn drop(&mut self) { unsafe { - if self.itr.is_some() { - htslib::hts_itr_destroy(self.itr.unwrap()); + if let Some(itr) = self.itr { + htslib::hts_itr_destroy(itr); } htslib::tbx_destroy(self.tbx); htslib::hts_close(self.hts_file);