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}