xpct/matchers/strings/
regex.rs

1use regex::Regex;
2
3use crate::core::Match;
4use crate::matchers::Mismatch;
5
6/// The matcher for [`match_regex`].
7///
8/// [`match_regex`]: crate::match_regex
9#[derive(Debug)]
10pub struct RegexMatcher {
11    regex: Result<Regex, regex::Error>,
12}
13
14impl RegexMatcher {
15    /// Create a new [`RegexMatcher`] from the expected regex.
16    ///
17    /// If the given regex is invalid, the matcher will return an error.
18    pub fn new(regex: impl AsRef<str>) -> Self {
19        Self {
20            regex: Regex::new(regex.as_ref()),
21        }
22    }
23}
24
25impl<Actual> Match<Actual> for RegexMatcher
26where
27    Actual: AsRef<str>,
28{
29    type Fail = Mismatch<String, Actual>;
30
31    fn matches(&mut self, actual: &Actual) -> crate::Result<bool> {
32        match &self.regex {
33            Ok(unwrapped_regex) => Ok(unwrapped_regex.is_match(actual.as_ref())),
34            Err(error) => Err(error.clone().into()),
35        }
36    }
37
38    fn fail(self, actual: Actual) -> Self::Fail {
39        // If the regex is invalid, `matches` will be called first, it will return an error, and
40        // this method will never be called. If something else is happening, it's a bug.
41        let unwrapped_regex = self.regex.expect(
42            "The given regex is invalid, but the matcher was never used. This shouldn't happen.",
43        );
44
45        Mismatch {
46            expected: unwrapped_regex.to_string(),
47            actual,
48        }
49    }
50}