minimap2_sys/
lib.rs

1#![allow(improper_ctypes)]
2#![allow(unsafe_op_in_unsafe_fn)]
3#![allow(non_upper_case_globals)]
4#![allow(non_camel_case_types)]
5#![allow(non_snake_case)]
6
7#[cfg(feature = "bindgen")]
8include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
9
10#[cfg(all(not(feature = "bindgen")))]
11include!("bindings.rs");
12
13use std::{mem::MaybeUninit, ops::{DerefMut, Deref}};
14
15unsafe impl Send for mm_idx_t {}
16unsafe impl Send for mm_idx_reader_t {}
17unsafe impl Send for mm_mapopt_t {}
18
19use paste::paste;
20
21// This is no longer good behavior.
22/*
23impl Drop for mm_idx_t {
24    fn drop(&mut self) {
25        unsafe { mm_idx_destroy(self) };
26    }
27} 
28*/
29
30
31/// A wrapper around `mm_idx_t` to ensure proper memory management.
32/// 
33/// If you use mm_idx_t directly, you must call `mm_idx_destroy` manually.
34/// Warning UB, there be dragons, etc...
35pub struct MmIdx {
36    pub idx: *mut mm_idx_t,
37}
38
39impl From<*mut mm_idx_t> for MmIdx {
40    fn from(idx: *mut mm_idx_t) -> Self {
41        MmIdx { idx }
42    }
43}
44
45impl Drop for MmIdx {
46    fn drop(&mut self) {
47        unsafe { mm_idx_destroy(self.idx) };
48    }
49}
50
51impl Deref for MmIdx {
52    type Target = mm_idx_t;
53
54    fn deref(&self) -> &Self::Target {
55        unsafe { &*self.idx }
56    }
57}
58
59impl DerefMut for MmIdx {
60    fn deref_mut(&mut self) -> &mut Self::Target {
61        unsafe { &mut *self.idx }
62    }
63}
64
65impl Default for mm_mapopt_t {
66    fn default() -> Self {
67        unsafe {
68            let mut opt = MaybeUninit::uninit();
69            mm_mapopt_init(opt.as_mut_ptr());
70            opt.assume_init()
71        }
72    }
73}
74
75impl Default for mm_idxopt_t {
76    fn default() -> Self {
77        unsafe {
78            let mut opt = MaybeUninit::uninit();
79            mm_idxopt_init(opt.as_mut_ptr());
80            opt.assume_init()
81        }
82    }
83}
84
85macro_rules! add_flag_methods {
86    ($ty:ty, $struct_name:ident, $(($set_name:ident, $unset_name:ident, $flag:expr)),+) => {
87        impl $struct_name {
88            $(
89                paste! {
90                    #[inline(always)]
91                    #[doc = "Set the " $flag " flag"]
92                    pub fn $set_name(&mut self) {
93                        self.flag |= $flag as $ty;
94                    }
95
96                    #[inline(always)]
97                    #[doc = "Unset the " $flag " flag"]
98                    pub fn $unset_name(&mut self) {
99                        self.flag &= !$flag as $ty;
100                    }
101                }
102            )*
103        }
104    };
105}
106
107add_flag_methods!(
108    i64,
109    mm_mapopt_t,
110    (set_no_dual, unset_no_dual, MM_F_NO_DUAL),
111    (set_no_diag, unset_no_diag, MM_F_NO_DIAG),
112    (set_cigar, unset_cigar, MM_F_CIGAR),
113    (set_out_sam, unset_out_sam, MM_F_OUT_SAM),
114    (set_no_qual, unset_no_qual, MM_F_NO_QUAL),
115    (set_out_cg, unset_out_cg, MM_F_OUT_CG),
116    (set_out_cs, unset_out_cs, MM_F_OUT_CS),
117    (set_splice, unset_splice, MM_F_SPLICE),
118    (set_splice_for, unset_splice_for, MM_F_SPLICE_FOR),
119    (set_splice_rev, unset_splice_rev, MM_F_SPLICE_REV),
120    (set_no_ljoin, unset_no_ljoin, MM_F_NO_LJOIN),
121    (set_out_cs_long, unset_out_cs_long, MM_F_OUT_CS_LONG),
122    (set_sr, unset_sr, MM_F_SR),
123    (set_frag_mode, unset_frag_mode, MM_F_FRAG_MODE),
124    (set_no_print_2nd, unset_no_print_2nd, MM_F_NO_PRINT_2ND),
125    (set_two_io_threads, unset_two_io_threads, MM_F_2_IO_THREADS),
126    (set_long_cigar, unset_long_cigar, MM_F_LONG_CIGAR),
127    (set_indep_seg, unset_indep_seg, MM_F_INDEPEND_SEG),
128    (set_splice_flank, unset_splice_flank, MM_F_SPLICE_FLANK),
129    (set_softclip, unset_softclip, MM_F_SOFTCLIP),
130    (set_for_only, unset_for_only, MM_F_FOR_ONLY),
131    (set_rev_only, unset_rev_only, MM_F_REV_ONLY),
132    (set_heap_sort, unset_heap_sort, MM_F_HEAP_SORT),
133    (set_all_chains, unset_all_chains, MM_F_ALL_CHAINS),
134    (set_out_md, unset_out_md, MM_F_OUT_MD),
135    (set_copy_comment, unset_copy_comment, MM_F_COPY_COMMENT),
136    (set_eqx, unset_eqx, MM_F_EQX),
137    (set_paf_no_hit, unset_paf_no_hit, MM_F_PAF_NO_HIT),
138    (set_no_end_flt, unset_no_end_flt, MM_F_NO_END_FLT),
139    (set_hard_mlevel, unset_hard_mlevel, MM_F_HARD_MLEVEL),
140    (set_sam_hit_only, unset_sam_hit_only, MM_F_SAM_HIT_ONLY),
141    (set_rmq, unset_rmq, MM_F_RMQ),
142    (set_qstrand, unset_qstrand, MM_F_QSTRAND),
143    (set_no_inv, unset_no_inv, MM_F_NO_INV),
144    (set_no_hash_name, unset_no_hash_name, MM_F_NO_HASH_NAME),
145    (set_splice_old, unset_splice_old, MM_F_SPLICE_OLD),
146    (set_secondary_seq, unset_secondary_seq, MM_F_SECONDARY_SEQ),
147    (set_out_ds, unset_out_ds, MM_F_OUT_DS)
148);
149
150add_flag_methods!(
151    std::os::raw::c_short,
152    mm_idxopt_t,
153    (set_hpc, unset_hpc, MM_I_HPC),
154    (set_no_seq, unset_no_seq, MM_I_NO_SEQ),
155    (set_no_name, unset_no_name, MM_I_NO_NAME)
156);
157
158// TODO: Add more tests!
159#[cfg(test)]
160mod tests {
161    use super::*;
162    use std::mem::MaybeUninit;
163
164    #[test]
165    fn set_index_and_mapping_opts() {
166        let mut mm_idxopt = MaybeUninit::uninit();
167        let mut mm_mapopt = MaybeUninit::uninit();
168
169        unsafe {
170            mm_set_opt(
171                std::ptr::null(),
172                mm_idxopt.as_mut_ptr(),
173                mm_mapopt.as_mut_ptr(),
174            )
175        };
176        println!("{:#?}", unsafe { mm_idxopt.assume_init() });
177        println!("{:#?}", unsafe { mm_mapopt.assume_init() }); // Run tests with --nocapture to see the output
178    }
179
180    #[test]
181    fn mapopt() {
182        let x: mm_mapopt_t = Default::default();
183    }
184
185    #[test]
186    fn idxopt() {
187        let x: mm_idxopt_t = Default::default();
188    }
189
190    #[test]
191    fn test_mapopt_flags() {
192        let mut opt = mm_mapopt_t::default();
193        opt.set_no_qual();
194        assert_eq!(opt.flag & MM_F_NO_QUAL as i64, MM_F_NO_QUAL as i64);
195
196        opt.unset_no_qual();
197        assert_eq!(opt.flag & MM_F_NO_QUAL as i64, 0_i64);
198    }
199
200    #[test]
201    fn test_idxopt_flags() {
202        let mut opt = mm_idxopt_t::default();
203        opt.set_hpc();
204        assert_eq!(opt.flag & MM_I_HPC as i16, MM_I_HPC as i16);
205
206        opt.unset_hpc();
207        assert_eq!(opt.flag & MM_I_HPC as i16, 0_i16);
208    }
209}