fuzzy_filter/
lib.rs

1//! A fast implementation (`O(n)`) of fuzzy-filtering.
2
3/// This function takes two strings: the filter, and the string to test against ("other").
4/// It runs through "other" and determines if it matches "filter", and returns the resulting `bool`
5pub fn matches<'a>(filter: &'a str, other: &'a str) -> bool {
6  let fzy = FuzzyFilter { filter };
7  fzy.matches(other)
8}
9
10/// A re-usable struct that you can repeatedly call `matches(...)` against
11pub struct FuzzyFilter<'a> {
12  filter: &'a str,
13}
14impl<'a> FuzzyFilter<'a> {
15  /// Constructs a `FuzzyFilter` instance with the given filter.
16  pub fn new(filter: &'a str) -> FuzzyFilter {
17    FuzzyFilter { filter }
18  }
19
20  /// This function takes the string to test the filter against ("other").
21  /// It runs through "other", determines if it matches the stored "filter"
22  /// and returns the resulting `bool`
23  pub fn matches(&self, other: &'a str) -> bool {
24    let mut filter_chars = self.filter.chars().peekable();
25    for other_c in other.chars() {
26      // advance filter_chars iff other_chars.next() == filter_chars.peek()
27      match filter_chars.peek() {
28        Some(filter_c) if *filter_c == other_c => {
29          filter_chars.next();
30        }
31        _ => {}
32      }
33
34      // if we've reached the end of filter_chars,
35      // return true
36      if filter_chars.peek().is_none() {
37        return true;
38      }
39    }
40    false
41  }
42}
43
44#[cfg(test)]
45mod tests {
46  use crate::matches;
47
48  #[test]
49  fn empty() {
50    assert_eq!(matches("", ""), false);
51  }
52
53  #[test]
54  fn exact() {
55    assert_eq!(matches("abc", "abc"), true);
56  }
57
58  #[test]
59  fn test1() {
60    assert_eq!(matches("abc", "alpha beta"), false);
61    assert_eq!(matches("abc", "alpha beta charlie"), true);
62  }
63
64  #[test]
65  fn test2() {
66    assert_eq!(matches("ppb", "pepsi polar bears"), true);
67    assert_eq!(matches("ppbz", "pepsi polar bears"), false);
68    assert_eq!(matches("ppbs", "pepsi polar bears"), true);
69  }
70}