diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 41fe6f134..d13852f90 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -846,8 +846,11 @@ impl IndexedReader { return Err(Error::InvalidTid { tid }); } + // Map unmapped reads (tid == -1) to the last slot (nref) to avoid usize wrapping. + let count_idx = if tid == -1 { nref } else { tid as usize }; + if tid != last_tid { - if (last_tid >= -1) && (counts[tid as usize][0] + counts[tid as usize][1]) > 0 { + if (last_tid >= -1) && (counts[count_idx][0] + counts[count_idx][1]) > 0 { return Err(Error::BamUnsorted); } last_tid = tid; @@ -858,7 +861,7 @@ impl IndexedReader { } else { 0 }; - counts[(*b).core.tid as usize][idx] += 1; + counts[count_idx][idx] += 1; } if ret == -1 { @@ -1029,8 +1032,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); } @@ -3166,6 +3169,20 @@ CCCCCCCCCCCCCCCCCCC"[..], assert_eq!(expected, actual); } + #[test] + fn test_slow_idxstats_cram_unmapped() { + let mut reader = IndexedReader::from_path("test/test_cram_unmapped.cram").unwrap(); + reader.set_reference("test/test_cram.fa").unwrap(); + let expected = vec![ + (0, 120, 2, 0), + (1, 120, 2, 0), + (2, 120, 2, 0), + (-1, 0, 0, 2), + ]; + let actual = reader.index_stats().unwrap(); + assert_eq!(expected, actual); + } + // #[test] // fn test_number_mapped_and_unmapped_cram() { // let mut reader = IndexedReader::from_path("test/test_cram.cram").unwrap(); 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); diff --git a/test/test_cram_unmapped.cram b/test/test_cram_unmapped.cram new file mode 100644 index 000000000..acf26eaf4 Binary files /dev/null and b/test/test_cram_unmapped.cram differ diff --git a/test/test_cram_unmapped.cram.crai b/test/test_cram_unmapped.cram.crai new file mode 100644 index 000000000..f0147797d Binary files /dev/null and b/test/test_cram_unmapped.cram.crai differ