1use log::*;
2use std::ffi::CStr;
3use std::ffi::CString;
4
5pub struct Hmm {
6 pub c_hmm: *mut libhmmer_sys::P7_HMM,
7}
8
9impl Hmm {
10 pub fn read_hmms_from_path(path: &std::path::Path) -> Result<Vec<Hmm>, &'static str> {
11 #[allow(unused_mut)]
13 let mut errbuf = CString::new(vec![1; libhmmer_sys::eslERRBUFSIZE as usize])
14 .unwrap()
15 .into_raw();
16
17 let hmmfile = CString::new(path.to_string_lossy().as_bytes())
18 .unwrap()
19 .into_raw();
20
21 let mut hfp: *mut libhmmer_sys::P7_HMMFILE = std::ptr::null_mut();
23 let status1 = unsafe {
24 libhmmer_sys::p7_hmmfile_OpenE(hmmfile, std::ptr::null_mut(), &mut hfp, errbuf)
25 };
26 if status1 != 0 {
28 error!("Error in initial reading of HMM file");
29 return Err("Error in initial reading of HMM file");
30 }
31 debug!("HMM file opened successfully");
32
33 let mut hmms = Vec::new();
35 loop {
36 let mut abc: *mut libhmmer_sys::ESL_ALPHABET = std::ptr::null_mut();
39 let mut hmm: *mut libhmmer_sys::P7_HMM = std::ptr::null_mut();
41
42 let status2 = unsafe { libhmmer_sys::p7_hmmfile_Read(hfp, &mut abc, &mut hmm) };
43 if status2 == libhmmer_sys::eslEOF as i32 {
44 debug!("EOF reached");
45 break;
46 } else if status2 != 0 {
47 error!("Error in reading HMM from opened file");
48 return Err("Error in reading HMM from opened file");
49 }
50 debug!("HMM read successfully");
51 hmms.push(Hmm { c_hmm: hmm });
52 }
53
54 unsafe {
56 let _ = CString::from_raw(errbuf);
57 let _ = CString::from_raw(hmmfile);
58 }
59
60 Ok(hmms)
61 }
62
63 pub fn c_alphabet(&self) -> *const libhmmer_sys::ESL_ALPHABET {
64 unsafe { (*self.c_hmm).abc }
65 }
66
67 pub fn name(&self) -> String {
68 return unsafe {
69 CStr::from_ptr((*self.c_hmm).name)
70 .to_string_lossy()
71 .to_string()
72 };
73 }
74
75 pub fn length(&self) -> u32 {
76 unsafe { (*self.c_hmm).M as u32 }
77 }
78
79 pub fn acc(&self) -> String {
80 let my_acc = unsafe { (*self.c_hmm).acc };
81 if my_acc.is_null() {
82 "".to_string() } else {
84 return unsafe { CStr::from_ptr(my_acc).to_string_lossy().to_string() };
85 }
86 }
87
88 pub fn desc(&self) -> String {
89 let my_desc = unsafe { (*self.c_hmm).desc };
90 if my_desc.is_null() {
91 "".to_string() } else {
93 return unsafe { CStr::from_ptr(my_desc).to_string_lossy().to_string() };
94 }
95 }
96}
97
98impl Drop for Hmm {
99 fn drop(&mut self) {
100 unsafe {
101 libhmmer_sys::p7_hmm_Destroy(self.c_hmm);
102 }
103 }
104}