Skip to main content

fuzzy_regex/
types.rs

1//! Core types for fuzzy matching limits and penalties.
2pub type NumEdits = u8;
3pub type Distance = u16;
4
5/// Limits on the number of edit operations allowed during fuzzy matching.
6///
7/// Edit operations include:
8/// - **Insertions**: Extra characters in the text that aren't in the pattern
9/// - **Deletions**: Characters in the pattern that are missing from the text
10/// - **Substitutions**: Characters that differ between pattern and text
11/// - **Swaps**: Adjacent character transpositions
12///
13/// You can set a total edit limit with `edits()`, or individual limits for each
14/// operation type. When individual limits are set without a total, the total is
15/// computed as the sum of individual limits.
16#[derive(Debug, Default, Clone, PartialEq)]
17pub struct FuzzyLimits {
18    insertions: Option<NumEdits>,
19    deletions: Option<NumEdits>,
20    substitutions: Option<NumEdits>,
21    swaps: Option<NumEdits>,
22    edits: Option<NumEdits>,
23}
24
25impl FuzzyLimits {
26    /// Create new empty fuzzy limits (exact match only).
27    #[must_use]
28    pub fn new() -> Self {
29        Self::default()
30    }
31
32    /// Set the maximum number of insertions allowed.
33    #[must_use]
34    pub fn insertions(mut self, num: NumEdits) -> Self {
35        self.insertions = Some(num);
36        self
37    }
38
39    /// Set the maximum number of deletions allowed.
40    #[must_use]
41    pub fn deletions(mut self, num: NumEdits) -> Self {
42        self.deletions = Some(num);
43        self
44    }
45
46    /// Set the maximum number of substitutions allowed.
47    #[must_use]
48    pub fn substitutions(mut self, num: NumEdits) -> Self {
49        self.substitutions = Some(num);
50        self
51    }
52
53    /// Set the maximum number of swaps (transpositions) allowed.
54    #[must_use]
55    pub fn swaps(mut self, num: NumEdits) -> Self {
56        self.swaps = Some(num);
57        self
58    }
59
60    /// Set the maximum total number of edits allowed.
61    #[must_use]
62    pub fn edits(mut self, num: NumEdits) -> Self {
63        self.edits = Some(num);
64        self
65    }
66
67    /// Get the maximum total edits allowed.
68    #[must_use]
69    pub fn get_edits(&self) -> Option<NumEdits> {
70        self.edits
71    }
72
73    /// Get the maximum insertions allowed.
74    #[must_use]
75    pub fn get_insertions(&self) -> Option<NumEdits> {
76        self.insertions
77    }
78
79    /// Get the maximum deletions allowed.
80    #[must_use]
81    pub fn get_deletions(&self) -> Option<NumEdits> {
82        self.deletions
83    }
84
85    /// Get the maximum substitutions allowed.
86    #[must_use]
87    pub fn get_substitutions(&self) -> Option<NumEdits> {
88        self.substitutions
89    }
90
91    /// Get the maximum swaps allowed.
92    #[must_use]
93    pub fn get_swaps(&self) -> Option<NumEdits> {
94        self.swaps
95    }
96}
97
98/// Penalty weights for different edit operations.
99///
100/// These weights are used to calculate a weighted edit distance where different
101/// operations can have different costs. Lower penalties mean the operation is
102/// considered "cheaper" during matching.
103#[derive(Debug, Clone)]
104pub struct FuzzyPenalties {
105    /// Penalty for inserting a character (extra char in text).
106    pub insertion: f32,
107    /// Penalty for deleting a character (missing char from pattern).
108    pub deletion: f32,
109    /// Penalty for substituting a character.
110    pub substitution: f32,
111    /// Penalty for swapping adjacent characters.
112    pub swap: f32,
113}
114
115impl Default for FuzzyPenalties {
116    fn default() -> Self {
117        let m = 1.3;
118        Self {
119            substitution: 1.1 * m,
120            insertion: 0.4 * m,
121            deletion: 0.7 * m,
122            swap: 0.4 * m,
123        }
124    }
125}
126
127impl FuzzyPenalties {
128    /// Set the insertion penalty.
129    #[must_use]
130    pub fn insertion(mut self, penalty: f32) -> Self {
131        self.insertion = penalty;
132        self
133    }
134
135    /// Set the deletion penalty.
136    #[must_use]
137    pub fn deletion(mut self, penalty: f32) -> Self {
138        self.deletion = penalty;
139        self
140    }
141
142    /// Set the substitution penalty.
143    #[must_use]
144    pub fn substitution(mut self, penalty: f32) -> Self {
145        self.substitution = penalty;
146        self
147    }
148
149    /// Set the swap penalty.
150    #[must_use]
151    pub fn swap(mut self, penalty: f32) -> Self {
152        self.swap = penalty;
153        self
154    }
155}