summaryrefslogtreecommitdiff
path: root/src/regex_set.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/regex_set.rs')
-rw-r--r--src/regex_set.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/regex_set.rs b/src/regex_set.rs
new file mode 100644
index 00000000..dbdb6565
--- /dev/null
+++ b/src/regex_set.rs
@@ -0,0 +1,69 @@
+//! A type that represents the union of a set of regular expressions.
+
+use regex::RegexSet as RxSet;
+
+// Yeah, I'm aware this is sorta crappy, should be cheaper to compile a regex
+// ORing all the patterns, I guess...
+
+/// A dynamic set of regular expressions.
+#[derive(Debug)]
+pub struct RegexSet {
+ items: Vec<String>,
+ set: Option<RxSet>,
+}
+
+impl RegexSet {
+ /// Is this set empty?
+ pub fn is_empty(&self) -> bool {
+ self.items.is_empty()
+ }
+
+ /// Extend this set with every regex in the iterator.
+ pub fn extend<I, S>(&mut self, iter: I)
+ where I: IntoIterator<Item = S>,
+ S: AsRef<str>
+ {
+ for s in iter.into_iter() {
+ self.insert(s)
+ }
+ }
+
+ /// Insert a new regex into this set.
+ pub fn insert<S>(&mut self, string: S)
+ where S: AsRef<str>
+ {
+ self.items.push(format!("^{}$", string.as_ref()));
+ self.set = None;
+ }
+
+ /// 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) {
+ self.set = match RxSet::new(&self.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();
+ self.set.as_ref().map(|set| set.is_match(s)).unwrap_or(false)
+ }
+}
+
+impl Default for RegexSet {
+ fn default() -> Self {
+ RegexSet {
+ items: vec![],
+ set: None,
+ }
+ }
+}