actix_router/
regex_set.rs

1//! Abstraction over `regex` and `regex-lite` depending on whether we have `unicode` crate feature
2//! enabled.
3
4use cfg_if::cfg_if;
5#[cfg(feature = "unicode")]
6pub(crate) use regex::{escape, Regex};
7#[cfg(not(feature = "unicode"))]
8pub(crate) use regex_lite::{escape, Regex};
9
10#[cfg(feature = "unicode")]
11#[derive(Debug, Clone)]
12pub(crate) struct RegexSet(regex::RegexSet);
13
14#[cfg(not(feature = "unicode"))]
15#[derive(Debug, Clone)]
16pub(crate) struct RegexSet(Vec<regex_lite::Regex>);
17
18impl RegexSet {
19    /// Create a new regex set.
20    ///
21    /// # Panics
22    ///
23    /// Panics if any path patterns are malformed.
24    pub(crate) fn new(re_set: Vec<String>) -> Self {
25        cfg_if! {
26            if #[cfg(feature = "unicode")] {
27                Self(regex::RegexSet::new(re_set).unwrap())
28            } else {
29                Self(re_set.iter().map(|re| Regex::new(re).unwrap()).collect())
30            }
31        }
32    }
33
34    /// Create a new empty regex set.
35    pub(crate) fn empty() -> Self {
36        cfg_if! {
37            if #[cfg(feature = "unicode")] {
38                Self(regex::RegexSet::empty())
39            } else {
40                Self(Vec::new())
41            }
42        }
43    }
44
45    /// Returns true if regex set matches `path`.
46    pub(crate) fn is_match(&self, path: &str) -> bool {
47        cfg_if! {
48            if #[cfg(feature = "unicode")] {
49                self.0.is_match(path)
50            } else {
51                self.0.iter().any(|re| re.is_match(path))
52            }
53        }
54    }
55
56    /// Returns index within `path` of first match.
57    pub(crate) fn first_match_idx(&self, path: &str) -> Option<usize> {
58        cfg_if! {
59            if #[cfg(feature = "unicode")] {
60                self.0.matches(path).into_iter().next()
61            } else {
62                Some(self.0.iter().enumerate().find(|(_, re)| re.is_match(path))?.0)
63            }
64        }
65    }
66}