hmmer_rs/
hmm.rs

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        // char          errbuf[eslERRBUFSIZE];
12        #[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        // Open file
22        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        // eslOK = 0
27        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        // Read each HMM
34        let mut hmms = Vec::new();
35        loop {
36            // ESL_ALPHABET *abc     = NULL;	/* alphabet (set from the HMM file)*/
37            // Set to NULL to not force alphabet
38            let mut abc: *mut libhmmer_sys::ESL_ALPHABET = std::ptr::null_mut();
39            // P7_HMM       *hmm     = NULL;
40            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        // retake pointer to free memory
55        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() // Otherwise we get a segfault
83        } 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() // Otherwise we get a segfault
92        } 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}