1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
//! A type that represents the union of a set of regular expressions.
use regex::RegexSet as RxSet;
use std::cell::Cell;
/// A dynamic set of regular expressions.
#[derive(Debug, Default)]
pub struct RegexSet {
items: Vec<String>,
matched: Vec<Cell<bool>>,
set: Option<RxSet>,
}
impl RegexSet {
/// Is this set empty?
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
/// Insert a new regex into this set.
pub fn insert<S>(&mut self, string: S)
where
S: AsRef<str>,
{
self.items.push(string.as_ref().to_owned());
self.matched.push(Cell::new(false));
self.set = None;
}
/// Returns slice of String from its field 'items'
pub fn get_items(&self) -> &[String] {
&self.items[..]
}
/// Returns an iterator over regexes in the set which didn't match any
/// strings yet.
pub fn unmatched_items(&self) -> impl Iterator<Item = &String> {
self.items.iter().enumerate().filter_map(move |(i, item)| {
if self.matched[i].get() {
return None;
}
Some(item)
})
}
/// Construct a RegexSet from the set of entries we've accumulated.
///
/// Must be called before calling `matches()`, or it will always return
/// false.
pub fn build(&mut self) {
let items = self.items.iter().map(|item| format!("^{}$", item));
self.set = match RxSet::new(items) {
Ok(x) => Some(x),
Err(e) => {
error!("Invalid regex in {:?}: {:?}", self.items, e);
None
}
}
}
/// Does the given `string` match any of the regexes in this set?
pub fn matches<S>(&self, string: S) -> bool
where
S: AsRef<str>,
{
let s = string.as_ref();
if let Some(set) = self.set.as_ref() {
let matches = set.matches(s);
if matches.matched_any() {
for i in matches.iter() {
self.matched[i].set(true);
}
return true;
}
}
false
}
}
|