regex_map/string.rs
1/// Associative container where the keys are regular expressions, based on the `regex::RegexSet` data structure.
2pub struct RegexMap<V> {
3 set: regex::RegexSet,
4 values: Vec<V>,
5}
6
7impl<V> RegexMap<V> {
8 /// Create a new `RegexMap` from iterator over (expression, value) pairs, where the expression is `&str`-like.
9 ///
10 /// ```
11 /// use regex_map::RegexMap;
12 ///
13 /// let map = RegexMap::new([
14 /// ("foo", 1),
15 /// ("bar", 2),
16 /// ("foobar", 3),
17 /// ("^foo$", 4),
18 /// ("^bar$", 5),
19 /// ("^foobar$", 6),
20 /// ]);
21 ///
22 /// assert_eq!(map.get("foo").cloned().collect::<Vec<_>>(), vec![1, 4]);
23 /// assert_eq!(map.get("bar").cloned().collect::<Vec<_>>(), vec![2, 5], );
24 /// assert_eq!(map.get("foobar").cloned().collect::<Vec<_>>(), vec![1, 2, 3, 6]);
25 /// assert_eq!(map.get("XXX foo XXX").cloned().collect::<Vec<_>>(), vec![1]);
26 /// assert_eq!(map.get("XXX bar XXX").cloned().collect::<Vec<_>>(), vec![2]);
27 /// ```
28 pub fn new<I, S>(items: I) -> Self
29 where
30 I: IntoIterator<Item = (S, V)>,
31 S: AsRef<str>,
32 {
33 let mut exprs = Vec::new();
34 let mut values = Vec::new();
35 for (expr, value) in items {
36 exprs.push(expr);
37 values.push(value);
38 }
39
40 let set = regex::RegexSet::new(exprs).unwrap();
41 RegexMap { set, values }
42 }
43
44 /// Get an iterator over all values whose regular expression matches the given key.
45 ///
46 /// To get first matching value, use can use `.next()` on the returned iterator:
47 ///
48 /// ```
49 /// use regex_map::RegexMap;
50 ///
51 /// let map = RegexMap::new([
52 /// ("foo", 1),
53 /// ("bar", 2),
54 /// ]);
55 ///
56 /// assert_eq!(map.get("foo").next(), Some(&1));
57 /// ```
58 pub fn get(&self, key: &str) -> impl Iterator<Item = &V> {
59 self.set
60 .matches(key)
61 .into_iter()
62 .map(move |i| &self.values[i])
63 }
64
65 /// Check if the given key matches any of the regular expressions.
66 pub fn contains_key(&self, key: &str) -> bool {
67 self.set.is_match(key)
68 }
69}