Skip to main content

pistonite_cu/str/
regex.rs

1use cu::pre::*;
2
3/// Deserializable regex
4#[derive(Clone)]
5pub struct Regex {
6    inner: regex::Regex,
7
8    #[cfg(feature = "serde")]
9    lit: String,
10}
11impl Regex {
12    pub fn new(s: &str) -> cu::Result<Self> {
13        let inner = cu::check!(regex::Regex::new(s), "failed to build regex from {s:?}")?;
14        #[cfg(feature = "serde")]
15        let s = Self {
16            inner,
17            lit: s.to_string(),
18        };
19        #[cfg(not(feature = "serde"))]
20        let s = Self { inner };
21        Ok(s)
22    }
23}
24impl std::ops::Deref for Regex {
25    type Target = regex::Regex;
26    fn deref(&self) -> &Self::Target {
27        &self.inner
28    }
29}
30impl std::ops::DerefMut for Regex {
31    fn deref_mut(&mut self) -> &mut Self::Target {
32        &mut self.inner
33    }
34}
35impl std::fmt::Display for Regex {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        write!(f, "{}", self.lit)
38    }
39}
40impl std::fmt::Debug for Regex {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        write!(f, "Regex({})", self.inner)
43    }
44}
45impl PartialEq for Regex {
46    fn eq(&self, other: &Self) -> bool {
47        self.lit == other.lit
48    }
49}
50impl Eq for Regex {}
51impl PartialOrd for Regex {
52    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
53        Some(self.cmp(other))
54    }
55}
56impl Ord for Regex {
57    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
58        self.lit.cmp(&other.lit)
59    }
60}
61impl std::hash::Hash for Regex {
62    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
63        self.lit.hash(state);
64    }
65}
66impl Regex {
67    /// Get the string that this regex was created from
68    pub fn to_str(&self) -> &str {
69        &self.lit
70    }
71}
72impl From<Regex> for regex::Regex {
73    fn from(value: Regex) -> Self {
74        value.inner
75    }
76}
77
78#[cfg(feature = "serde")]
79impl Serialize for Regex {
80    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
81        s.serialize_str(&self.lit)
82    }
83}
84
85#[cfg(feature = "serde")]
86impl<'de> Deserialize<'de> for Regex {
87    fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
88        return d.deserialize_str(Visitor);
89        struct Visitor;
90        impl<'de> serde::de::Visitor<'de> for Visitor {
91            type Value = Regex;
92            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
93                write!(f, "a regular expression")
94            }
95            fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
96                match regex::Regex::new(v) {
97                    Err(e) => Err(serde::de::Error::custom(format!(
98                        "invalid regular expression '{v}': {e}"
99                    ))),
100                    Ok(x) => Ok(Regex {
101                        inner: x,
102                        lit: v.to_string(),
103                    }),
104                }
105            }
106        }
107    }
108}