From 0b312a9ce04b64516b32d42b1a72d52b9ac3c27b Mon Sep 17 00:00:00 2001 From: Daniel Baker Date: Thu, 28 Sep 2023 13:05:44 -0700 Subject: [PATCH] Add rust_htslib::bcf::index::build, to build a bcf/vcf index. --- src/bcf/index.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ src/bcf/mod.rs | 1 + 2 files changed, 72 insertions(+) create mode 100644 src/bcf/index.rs diff --git a/src/bcf/index.rs b/src/bcf/index.rs new file mode 100644 index 000000000..9c548a5a1 --- /dev/null +++ b/src/bcf/index.rs @@ -0,0 +1,71 @@ +use crate::{htslib, utils}; + +#[derive(Debug)] +pub struct BcfBuildError { + pub msg: String, +} + +/// Index type to build. +pub enum Type { + /// Tabix index + Tbx, + /// CSI index, with given minimum shift + Csi(u32), +} + +impl Type { + fn min_shift(&self) -> i32 { + match self { + Self::Tbx => 0, + Self::Csi(x) => *x as i32, + } + } +} + +impl BcfBuildError { + pub fn error_message(error: i32) -> &'static str { + match error { + -1 => "indexing failed", + -2 => "opening @fn failed", + -3 => "format not indexable", + -4 => "failed to create and/or save the index", + _ => "unknown error", + } + } +} +impl std::error::Error for BcfBuildError {} + +impl std::fmt::Display for BcfBuildError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "BcfBuildError{{msg: {}}}", self.msg) + } +} + +/// Build a bcf or vcf.gz index. +/// Builds tbi or csi depending on index_type. +pub fn build>( + bcf_path: P, + idx_path: Option

, + n_threads: u32, + index_type: Type, +) -> Result<(), BcfBuildError> { + let min_shift = index_type.min_shift(); + let idx_path_cstr = idx_path.map(|p| utils::path_to_cstring(&p).expect("path_to_cstring")); + let ret = unsafe { + htslib::bcf_index_build3( + utils::path_to_cstring(&bcf_path).unwrap().as_ptr(), + idx_path_cstr.map_or(std::ptr::null(), |p| p.as_ptr()), + min_shift, + n_threads as i32, + ) + }; + match ret { + 0 => Ok(()), + e => Err(BcfBuildError { + msg: format!( + "Failed to build bcf index. Error: {e:?}/{}", + BcfBuildError::error_message(e) + ), + }), + } +} diff --git a/src/bcf/mod.rs b/src/bcf/mod.rs index 7669911be..ab10dec0d 100644 --- a/src/bcf/mod.rs +++ b/src/bcf/mod.rs @@ -112,6 +112,7 @@ use url::Url; pub mod buffer; pub mod header; +pub mod index; pub mod record; use crate::bcf::header::{HeaderView, SampleSubset};