1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use std::path::Path;
use std::ptr;
use crate::bam::errors::{Error, Result};
use crate::htslib;
use crate::utils;
pub enum Type {
BAI,
CSI(u32),
}
pub fn build<P: AsRef<Path>>(
bam_path: P,
idx_path: Option<P>,
idx_type: Type,
n_threads: u32,
) -> Result<()> {
let min_shift = match idx_type {
Type::BAI => 0,
Type::CSI(min_shift) => min_shift as i32,
};
let idx_path_cstr;
let idx_path_ptr = if let Some(p) = idx_path {
idx_path_cstr =
utils::path_to_cstring(&p).expect("path_to_cstring unexpectedly returned with Err");
idx_path_cstr.as_ptr()
} else {
ptr::null()
};
let ret = unsafe {
htslib::sam_index_build3(
utils::path_to_cstring(&bam_path).unwrap().as_ptr(),
idx_path_ptr,
min_shift,
n_threads as i32,
)
};
match ret {
0 => Ok(()),
-1 => Err(Error::BuildIndex),
-2 => Err(Error::Open {
target: bam_path.as_ref().to_str().unwrap().to_owned(),
}),
-3 => Err(Error::NotIndexable),
-4 => Err(Error::WriteIndex),
e => panic!("unexpected error code from sam_index_build3: {}", e),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_index_build() {
let test_bam = "test/test_index_build.bam";
let idx1 = "test/results/test1.bam.bai";
build(test_bam, Some(idx1), Type::BAI, 1).unwrap();
assert!(Path::new(idx1).exists());
let idx2 = "test/results/test2.bam.bai";
build(test_bam, Some(idx2), Type::BAI, 2).unwrap();
assert!(Path::new(idx2).exists());
let idx3 = "test/results/test3.bam.csi";
build(test_bam, Some(idx3), Type::CSI(2), 2).unwrap();
assert!(Path::new(idx3).exists());
build(test_bam, None, Type::CSI(5), 2).unwrap();
assert!(Path::new("test/test_index_build.bam.csi").exists());
}
}