ragc_core/ffi/
preprocessing.rs

1// FFI wrapper for preprocessing operations
2
3use crate::preprocessing::preprocess_raw_contig;
4
5/// Preprocess raw contig (in-place) by converting ASCII to numeric codes
6///
7/// Matches C++ AGC's preprocess_raw_contig() behavior:
8/// - Filters bytes >= 64 (letter characters)
9/// - Converts using cnv_num lookup table
10/// - Removes non-letter characters
11/// - Returns new length after preprocessing
12///
13/// # Safety
14/// - contig_ptr must point to a valid vector allocation of at least contig_capacity elements
15/// - The caller must resize the vector to the returned length
16/// - Caller maintains ownership of the allocation
17#[no_mangle]
18pub extern "C" fn ragc_preprocess_raw_contig(
19    contig_ptr: *mut u8,
20    contig_len: usize,
21    contig_capacity: usize,
22) -> usize {
23    unsafe {
24        // Reconstruct the Vec from raw parts (temporarily borrow ownership)
25        let mut contig = Vec::from_raw_parts(contig_ptr, contig_len, contig_capacity);
26
27        // Call the Rust implementation
28        preprocess_raw_contig(&mut contig);
29
30        // Get the new length after preprocessing
31        let new_len = contig.len();
32
33        // Prevent Rust from freeing the allocation (C++ owns it)
34        std::mem::forget(contig);
35
36        new_len
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn test_ffi_preprocess_raw_contig() {
46        let mut data = b"ACGT".to_vec();
47        let ptr = data.as_mut_ptr();
48        let len = data.len();
49        let cap = data.capacity();
50
51        // Prevent Rust from freeing - we're simulating C++ ownership
52        std::mem::forget(data);
53
54        // Call FFI function
55        let new_len = ragc_preprocess_raw_contig(ptr, len, cap);
56
57        // Reconstruct to check result
58        let result = unsafe { Vec::from_raw_parts(ptr, new_len, cap) };
59        assert_eq!(result, vec![0, 1, 2, 3]);
60    }
61}