diff --git a/src/errors.rs b/src/errors.rs index d23b9e317..680bd5f33 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -31,6 +31,8 @@ pub enum Error { // Errors for faidx #[error("The given position is too large to be converted to i64")] FaidxPositionTooLarge, + #[error("bad conversion of sequence name")] + FaidxBadSeqName, // Errors for Tbx #[error("previous iterator generation failed")] diff --git a/src/faidx/mod.rs b/src/faidx/mod.rs index 18ac72000..a1f43e894 100644 --- a/src/faidx/mod.rs +++ b/src/faidx/mod.rs @@ -99,6 +99,33 @@ impl Reader { let bytes = self.fetch_seq(name, begin, end)?; Ok(std::str::from_utf8(bytes).unwrap().to_owned()) } + + /// Fetches the number of sequences in the fai index + pub fn n_seqs(&self) -> u64 { + let n = unsafe { htslib::faidx_nseq(self.inner) }; + n as u64 + } + + /// Fetches the i-th sequence name + /// + /// # Arguments + /// + /// * `i` - index to query + pub fn seq_name(&self, i: i32) -> Result { + let cname = unsafe { + let ptr = htslib::faidx_iseq(self.inner, i); + ffi::CStr::from_ptr(ptr) + }; + + let out = match cname.to_str() { + Ok(s) => s.to_string(), + Err(_) => { + return Err(Error::FaidxBadSeqName); + } + }; + + Ok(out) + } } #[cfg(test)] @@ -198,4 +225,17 @@ mod tests { let res = r.fetch_seq("chr1", position_too_large, position_too_large + 1); assert_eq!(res, Err(Error::FaidxPositionTooLarge)); } + + #[test] + fn faidx_n_seqs() { + let r = open_reader(); + assert_eq!(r.n_seqs(), 3); + } + + #[test] + fn faidx_seq_name() { + let r = open_reader(); + let n = r.seq_name(1).unwrap(); + assert_eq!(n, "chr2"); + } }