Skip to main content

yara_mapper/
options.rs

1/// Sensitivity level for YARA's seed-and-extend pipeline.
2///
3/// - `Low`: Only two rounds of seeding (0-error and 1-error seeds).
4/// - `High`: Three rounds of seeding (adds 2-error seeds). Default.
5/// - `Full`: Same as `High` but uses edit-distance seeds instead of Hamming.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[repr(i32)]
8pub enum Sensitivity {
9    Low = 0,
10    High = 1,
11    Full = 2,
12}
13
14/// How secondary alignments are reported.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16#[repr(i32)]
17pub enum SecondaryMode {
18    /// Encode secondary alignments in the XA tag of the primary record.
19    Tag = 0,
20    /// Emit secondary alignments as separate records with the SECONDARY flag.
21    Record = 1,
22    /// Do not report secondary alignments.
23    Omit = 2,
24}
25
26/// Configuration options for the YARA mapper.
27///
28/// Use [`MapperOptions::default()`] for sensible defaults matching YARA's
29/// command-line defaults, then override individual fields as needed.
30#[derive(Debug, Clone)]
31pub struct MapperOptions {
32    /// Maximum error rate as a fraction of read length (default 0.05 = 5%).
33    pub error_rate: f32,
34    /// Strata rate — fraction of additional errors beyond the best alignment
35    /// to report (default 0.00).
36    pub strata_rate: f32,
37    /// Fixed strata count (alternative to `strata_rate`). Set to `None` to
38    /// use `strata_rate` instead.
39    pub strata_count: Option<u32>,
40    /// Sensitivity level (default `High`).
41    pub sensitivity: Sensitivity,
42    /// Number of threads for OpenMP parallelism (default: available cores).
43    pub threads: usize,
44    /// How to report secondary alignments (default `Tag`).
45    pub secondary_mode: SecondaryMode,
46    /// Whether to align secondary matches (compute CIGAR). Only meaningful
47    /// when `secondary_mode` is `Tag` or `Record`.
48    pub align_secondary: bool,
49    /// Whether to verify mate-pair matches (paired-end rescue). Default true.
50    pub verify_matches: bool,
51    /// Verbosity level (0 = silent, 1 = stats, 2 = detailed).
52    pub verbose: u32,
53    /// Expected library (insert) length. 0 = auto-estimate from the data.
54    pub library_length: u32,
55    /// Expected library standard deviation. 0 = auto-estimate.
56    pub library_dev: u32,
57}
58
59impl Default for MapperOptions {
60    fn default() -> Self {
61        Self {
62            error_rate: 0.05,
63            strata_rate: 0.00,
64            strata_count: None,
65            sensitivity: Sensitivity::High,
66            threads: std::thread::available_parallelism().map(std::num::NonZero::get).unwrap_or(1),
67            secondary_mode: SecondaryMode::Tag,
68            align_secondary: false,
69            verify_matches: true,
70            verbose: 0,
71            library_length: 0,
72            library_dev: 0,
73        }
74    }
75}
76
77impl MapperOptions {
78    #[expect(
79        clippy::cast_possible_wrap,
80        clippy::cast_possible_truncation,
81        reason = "FFI boundary: all values fit in i32 for the C API"
82    )]
83    pub(crate) fn to_ffi(&self) -> yara_mapper_sys::YaraMapperOptions {
84        yara_mapper_sys::YaraMapperOptions {
85            error_rate: self.error_rate,
86            strata_rate: self.strata_rate,
87            strata_count: self.strata_count.map_or(-1, |c| c as i32),
88            sensitivity: self.sensitivity as i32,
89            threads: self.threads as i32,
90            secondary_mode: self.secondary_mode as i32,
91            align_secondary: i32::from(self.align_secondary),
92            verify_matches: i32::from(self.verify_matches),
93            verbose: self.verbose as i32,
94            library_length: self.library_length as i32,
95            library_dev: self.library_dev as i32,
96        }
97    }
98}