hex_patch/fuzzer/
fuzzer.rs1pub fn fuzzy_search_cloned<T>(key: &str, entries: &[T]) -> Vec<T>
2where
3 T: AsRef<str> + Clone,
4{
5 let mut ret = entries.to_vec();
6 fuzzy_search_in_place(key, &mut ret);
7 ret
8}
9
10pub fn fuzzy_search_in_place<T>(key: &str, entries: &mut [T])
11where
12 T: AsRef<str> + Clone,
13{
14 entries.sort_by_cached_key(|source| -score(source.as_ref(), key));
15}
16
17fn score(source: &str, key: &str) -> isize {
18 let mut score = 0;
19
20 let char_found_bonus = 10;
21 let key_char_not_found_penalty = -5;
22 let self_char_not_found_penalty = -1;
23
24 let mut key_chars = key.chars();
25 let self_chars = source.chars();
26 let mut current_key_char = key_chars.next();
27 for self_char in self_chars {
28 if let Some(key_char) = current_key_char {
29 if self_char == key_char {
30 score += char_found_bonus;
31 current_key_char = key_chars.next();
32 } else {
33 score += self_char_not_found_penalty;
34 }
35 } else {
36 break;
37 }
38 }
39 for _ in key_chars {
40 score += key_char_not_found_penalty;
41 }
42 score
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn test_fuzzy_search() {
51 let entries = vec!["abc", "def", "ghi", "jkl"];
52 let result = fuzzy_search_cloned("d", &entries);
53 assert_eq!(result, vec!["def", "abc", "ghi", "jkl"]);
54 }
55}