Skip to main content

yara_mapper_sys/
lib.rs

1//! Low-level FFI bindings to the YARA read mapper C++ shim.
2//!
3//! This crate compiles a C++ shim layer that wraps YARA's SeqAn2-based template code
4//! and exposes a C-compatible API for loading FM indices, ingesting reads, and retrieving
5//! alignment results as flat structs.
6
7#![allow(non_camel_case_types)]
8
9use std::os::raw::{c_char, c_int};
10
11// ---------------------------------------------------------------------------
12// Opaque handle
13// ---------------------------------------------------------------------------
14
15/// Opaque handle to a fully-configured YARA Mapper instance.
16/// Allocated and owned by the C++ side; freed via [`yara_mapper_close`].
17#[repr(C)]
18pub struct YaraMapperHandle {
19    _opaque: [u8; 0],
20}
21
22// ---------------------------------------------------------------------------
23// Option / input / output structs (must match yara_shim.h exactly)
24// ---------------------------------------------------------------------------
25
26/// Mapper configuration passed to [`yara_mapper_open`].
27#[repr(C)]
28#[derive(Debug, Clone)]
29pub struct YaraMapperOptions {
30    pub error_rate: f32,
31    pub strata_rate: f32,
32    pub strata_count: i32,
33    pub sensitivity: i32,
34    pub threads: i32,
35    pub secondary_mode: i32,
36    pub align_secondary: i32,
37    pub verify_matches: i32,
38    pub verbose: i32,
39    pub library_length: i32,
40    pub library_dev: i32,
41}
42
43/// A batch of paired-end reads to map.
44#[repr(C)]
45#[derive(Debug)]
46pub struct YaraReadBatch {
47    pub names: *const *const c_char,
48    pub r1_seqs: *const *const c_char,
49    pub r1_quals: *const *const c_char,
50    pub r2_seqs: *const *const c_char,
51    pub r2_quals: *const *const c_char,
52    pub count: usize,
53}
54
55/// A single alignment record returned by the mapper.
56#[repr(C)]
57#[derive(Debug, Clone)]
58#[allow(clippy::pub_underscore_fields)]
59pub struct YaraAlignmentRecord {
60    // Read identification
61    pub read_pair_index: u32,
62    pub is_read1: u8,
63
64    // Alignment position
65    pub contig_id: u32,
66    pub pos: u32,
67    pub is_reverse: u8,
68    pub is_secondary: u8,
69    pub is_unmapped: u8,
70
71    // Alignment quality
72    pub mapq: u8,
73    pub nm: u8,
74    pub x0: u16,
75    pub x1: u16,
76
77    // Mate info
78    pub mate_contig_id: u32,
79    pub mate_pos: u32,
80    pub tlen: i32,
81    pub flag: u16,
82
83    // CIGAR (BAM-encoded uint32 array: op | len<<4)
84    pub cigar: *mut u32,
85    pub cigar_len: u32,
86
87    // Sequence and quality (NULL for secondaries)
88    pub seq: *const c_char,
89    pub qual: *const c_char,
90    pub seq_len: u32,
91
92    // XA tag string (NULL if none)
93    pub xa: *const c_char,
94
95    // Internal: if set, seq/qual/cigar are pool-managed (not individually freed).
96    pub _pool_managed: u8,
97}
98
99// ---------------------------------------------------------------------------
100// FFI function declarations
101// ---------------------------------------------------------------------------
102
103// SAFETY: These functions are implemented in C++ (yara_shim.cpp) and compiled
104// via build.rs. The caller is responsible for passing valid pointers and
105// respecting the lifetime contracts documented in yara_shim.h.
106unsafe extern "C" {
107    /// Create a mapper and load the FM index.  Returns null on error, with
108    /// `error_buf` populated.
109    pub fn yara_mapper_open(
110        index_prefix: *const c_char,
111        opts: *const YaraMapperOptions,
112        error_buf: *mut c_char,
113        error_buf_len: usize,
114    ) -> *mut YaraMapperHandle;
115
116    /// Map a batch of paired-end reads.  Returns the number of output records
117    /// written to `out`, or -1 on error.
118    pub fn yara_mapper_map_paired(
119        handle: *mut YaraMapperHandle,
120        reads: *const YaraReadBatch,
121        out: *mut YaraAlignmentRecord,
122        out_capacity: usize,
123        error_buf: *mut c_char,
124        error_buf_len: usize,
125    ) -> i64;
126
127    /// Number of reference contigs in the loaded index.
128    pub fn yara_mapper_contig_count(handle: *const YaraMapperHandle) -> usize;
129
130    /// Name of the contig at `idx`. The returned pointer is valid for the
131    /// lifetime of the handle.
132    pub fn yara_mapper_contig_name(handle: *const YaraMapperHandle, idx: usize) -> *const c_char;
133
134    /// Length of the contig at `idx`.
135    pub fn yara_mapper_contig_length(handle: *const YaraMapperHandle, idx: usize) -> usize;
136
137    /// Free the mapper and all associated memory.
138    pub fn yara_mapper_close(handle: *mut YaraMapperHandle);
139
140    /// Free a record batch's C++-owned memory (cigar arrays, seq/qual strings,
141    /// XA strings).  Must be called after processing each batch.
142    pub fn yara_mapper_free_records(records: *mut YaraAlignmentRecord, count: usize);
143
144    /// Free a single record's C++-owned memory (cigar, seq, qual, xa).
145    pub fn yara_mapper_free_record(record: *mut YaraAlignmentRecord);
146}
147
148// ---------------------------------------------------------------------------
149// Indexer: opaque handle
150// ---------------------------------------------------------------------------
151
152/// Opaque handle to a YARA Indexer instance.
153/// Allocated and owned by the C++ side; freed via [`yara_indexer_close`].
154#[repr(C)]
155pub struct YaraIndexerHandle {
156    _opaque: [u8; 0],
157}
158
159// ---------------------------------------------------------------------------
160// Indexer: options struct (must match yara_indexer_shim.h exactly)
161// ---------------------------------------------------------------------------
162
163/// Indexer configuration passed to [`yara_indexer_build`].
164#[repr(C)]
165#[derive(Debug)]
166pub struct YaraIndexerOptions {
167    pub output_prefix: *const c_char,
168    pub tmp_dir: *const c_char,
169    pub verbose: c_int,
170}
171
172// ---------------------------------------------------------------------------
173// Indexer: FFI function declarations
174// ---------------------------------------------------------------------------
175
176// SAFETY: These functions are implemented in C++ (yara_indexer_shim.cpp) and
177// compiled via build.rs. The caller is responsible for passing valid pointers
178// and respecting the lifetime contracts documented in yara_indexer_shim.h.
179unsafe extern "C" {
180    /// Build an FM index from a FASTA file. Returns null on error, with
181    /// `error_buf` populated.
182    pub fn yara_indexer_build(
183        fasta_path: *const c_char,
184        opts: *const YaraIndexerOptions,
185        error_buf: *mut c_char,
186        error_buf_len: usize,
187    ) -> *mut YaraIndexerHandle;
188
189    /// Number of contigs in the built index.
190    pub fn yara_indexer_contig_count(handle: *const YaraIndexerHandle) -> usize;
191
192    /// Name of the contig at `idx`. The returned pointer is valid for the
193    /// lifetime of the handle.
194    pub fn yara_indexer_contig_name(handle: *const YaraIndexerHandle, idx: usize) -> *const c_char;
195
196    /// Length of the contig at `idx`.
197    pub fn yara_indexer_contig_length(handle: *const YaraIndexerHandle, idx: usize) -> usize;
198
199    /// Free the indexer handle and all associated memory.
200    pub fn yara_indexer_close(handle: *mut YaraIndexerHandle);
201}