gotham/router/tree/
regex.rs

1//! Defines the wrapping type for a segment-matching regex.
2
3use regex::Regex;
4
5use std::cmp::Ordering;
6use std::panic::AssertUnwindSafe;
7
8/// A unwind-safe wrapper for Regex that implements PartialEq, Eq, PartialOrd, and Ord.  These
9/// traits are implemented in a potentially error-prone way by comparing the underlying &str
10/// representations of the regular expression.
11///
12/// If the `ConstrainedSegmentRegex::is_match` traps a panic from `Regex::is_match`,
13/// `std::process::abort()` will be called and the program will terminate.
14pub struct ConstrainedSegmentRegex {
15    regex: AssertUnwindSafe<Regex>,
16}
17
18impl ConstrainedSegmentRegex {
19    /// Creates a new ConstrainedSegmentRegex from a provided string.
20    ///
21    /// It wraps the string in begin and end of line anchors to prevent it from matching more than
22    /// intended.
23    pub fn new(regex: &str) -> Self {
24        ConstrainedSegmentRegex {
25            regex: AssertUnwindSafe(Regex::new(&format!("^{}$", regex)).unwrap()),
26        }
27    }
28
29    /// Returns the pattern backing this regex as a `&str`.
30    #[inline]
31    pub(crate) fn as_str(&self) -> &str {
32        self.regex.as_str()
33    }
34
35    /// Wraps `regex::Regex::is_match` to return true if and only if the regex matches the string
36    /// given.
37    #[inline]
38    pub(crate) fn is_match(&self, s: &str) -> bool {
39        self.regex.is_match(s)
40    }
41}
42
43impl PartialEq for ConstrainedSegmentRegex {
44    fn eq(&self, other: &Self) -> bool {
45        self.regex.as_str() == other.regex.as_str()
46    }
47}
48
49impl Eq for ConstrainedSegmentRegex {}
50
51impl PartialOrd for ConstrainedSegmentRegex {
52    fn partial_cmp(&self, other: &ConstrainedSegmentRegex) -> Option<Ordering> {
53        Some(self.as_str().cmp(other.as_str()))
54    }
55}
56
57impl Ord for ConstrainedSegmentRegex {
58    fn cmp(&self, other: &Self) -> Ordering {
59        self.as_str().cmp(other.as_str())
60    }
61}
62
63impl Clone for ConstrainedSegmentRegex {
64    fn clone(&self) -> ConstrainedSegmentRegex {
65        ConstrainedSegmentRegex {
66            regex: AssertUnwindSafe(self.regex.0.clone()),
67        }
68    }
69}