1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Fuzzy matching and scoring engine.
//!
//! # Quick start
//!
//! ```rust
//! use neek_core::{has_match, score, score_positions};
//!
//! let needle = b"src";
//! let haystack = b"src/main.rs";
//!
//! assert!(has_match(needle, haystack));
//!
//! let s = score(needle, haystack);
//! println!("score: {s}");
//!
//! let mut positions = vec![0usize; needle.len()];
//! let s2 = score_positions(needle, haystack, &mut positions);
//! assert_eq!(s, s2);
//! println!("matched at positions: {:?}", positions);
//! ```
//!
//! # Configurable scoring
//!
//! The default free functions use [`config::Prefer::Contiguous`], which
//! rewards consecutive character runs (Gotoh DP with balanced gap penalties).
//!
//! To prefer prefix or suffix matches, construct a [`Scorer`] and use its
//! methods:
//!
//! ```rust
//! use neek_core::{Scorer, config::Prefer};
//!
//! let scorer = Scorer::new(Prefer::Prefix);
//! // "build" starts with 'b'; "table" has a contiguous "bl" mid-string.
//! // Prefix-biased scoring ranks "build" higher.
//! assert!(scorer.score(b"bl", b"build") > scorer.score(b"bl", b"table"));
//! ```
extern crate alloc;
pub use ;
pub use Prefer;
/// Numeric type used for all scores.
pub type Score = f64;
/// Returned when a candidate is an exact (case-insensitive) match for the
/// needle, or when the needle is empty and all candidates match trivially.
pub const SCORE_MAX: Score = f64INFINITY;
/// Returned when a candidate cannot be scored (too long, no match, or the
/// needle is empty at the `score` call site).
pub const SCORE_MIN: Score = f64NEG_INFINITY;
/// Maximum haystack/needle length that the DP scorer handles. Candidates
/// longer than this are given `SCORE_MIN` by `score` / `score_positions`.
pub const MATCH_MAX_LEN: usize = 1024;
/// A reusable scorer with a fixed [`Prefer`] setting.
///
/// Construct once and call [`Scorer::score`] / [`Scorer::score_positions`] for
/// each candidate. All three algorithms share the same Gotoh DP core; only
/// the gap-penalty constants differ.
///
/// The free functions [`score`] and [`score_positions`] are thin wrappers
/// around `Scorer::default()` (i.e. [`Prefer::Contiguous`]).
///
/// # Examples
///
/// ```rust
/// use neek_core::{Scorer, config::Prefer};
///
/// // Prefer matches that start early in each candidate.
/// let scorer = Scorer::new(Prefer::Prefix);
/// assert!(scorer.score(b"bl", b"build") > scorer.score(b"bl", b"table"));
///
/// // Prefer matches that end late in each candidate.
/// let scorer = Scorer::new(Prefer::Suffix);
/// assert!(scorer.score(b"le", b"cable") > scorer.score(b"le", b"label"));
/// ```