1#[macro_use]
2extern crate lazy_static;
3extern crate unicode_normalization;
4
5use std::borrow::Borrow;
6use unicode_normalization::UnicodeNormalization;
7
8mod fuzz_search;
9pub use fuzz_search::fuzzy_search_score;
10use fuzz_search::fuzzy_search_score_no_norm;
11
12pub fn best_matches<T>(pattern: &str, items: Vec<T>, n: usize) -> impl Iterator<Item = T>
13where
14 T: Borrow<str>,
15{
16 best_matches_scores(pattern, items, n).map(|(name, _)| name).take(n)
17}
18
19pub fn best_matches_scores<T>(
20 pattern: &str,
21 items: Vec<T>,
22 n: usize,
23) -> impl Iterator<Item = (T, isize)>
24where
25 T: Borrow<str>,
26{
27 let pattern = pattern.nfc().collect::<String>();
28
29 let mut items_scores = items
30 .into_iter()
31 .map(|name| {
32 let x = &name.borrow().nfc().collect::<String>();
33 (name, fuzzy_search_score_no_norm(&pattern, x))
34 })
35 .collect::<Vec<_>>();
36
37 items_scores.sort_by_key(|(_, x)| -x);
38
39 items_scores.into_iter().take(n)
40}
41
42pub fn best_matches_scores_key<T, F, K>(
43 pattern: &str,
44 items: Vec<T>,
45 f: F,
46 n: usize,
47) -> impl Iterator<Item = (T, isize)>
48where
49 F: Fn(&T) -> K,
50 K: Borrow<str>,
51{
52 let pattern = pattern.nfc().collect::<String>();
53
54 let mut items_scores = items
55 .into_iter()
56 .map(|name| {
57 let x = &f(&name).borrow().nfc().collect::<String>();
58 (name, fuzzy_search_score_no_norm(&pattern, x))
59 })
60 .collect::<Vec<_>>();
61
62 items_scores.sort_by_key(|(_, x)| -x);
63
64 items_scores.into_iter().take(n)
65}