hex_patch/fuzzer/
fuzzer.rs

1pub 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}