Line data Source code
1 : //! A `serde::{Deserialize,Serialize}` type for regexes.
2 :
3 : use std::ops::Deref;
4 :
5 1 : #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
6 : #[serde(transparent)]
7 : pub struct Regex(
8 : #[serde(
9 : deserialize_with = "deserialize_regex",
10 : serialize_with = "serialize_regex"
11 : )]
12 : regex::Regex,
13 : );
14 :
15 1 : fn deserialize_regex<'de, D>(deserializer: D) -> Result<regex::Regex, D::Error>
16 1 : where
17 1 : D: serde::de::Deserializer<'de>,
18 1 : {
19 1 : let s: String = serde::de::Deserialize::deserialize(deserializer)?;
20 1 : let re = regex::Regex::new(&s).map_err(serde::de::Error::custom)?;
21 1 : Ok(re)
22 1 : }
23 :
24 1 : fn serialize_regex<S>(re: ®ex::Regex, serializer: S) -> Result<S::Ok, S::Error>
25 1 : where
26 1 : S: serde::ser::Serializer,
27 1 : {
28 1 : serializer.collect_str(re.as_str())
29 1 : }
30 :
31 : impl Deref for Regex {
32 : type Target = regex::Regex;
33 :
34 2 : fn deref(&self) -> ®ex::Regex {
35 2 : &self.0
36 2 : }
37 : }
38 :
39 : impl PartialEq for Regex {
40 0 : fn eq(&self, other: &Regex) -> bool {
41 0 : // comparing the automatons would be quite complicated
42 0 : self.as_str() == other.as_str()
43 0 : }
44 : }
45 :
46 : impl Eq for Regex {}
47 :
48 : #[cfg(test)]
49 : mod tests {
50 :
51 : #[test]
52 1 : fn roundtrip() {
53 1 : let input = r#""foo.*bar""#;
54 1 : let re: super::Regex = serde_json::from_str(input).unwrap();
55 1 : assert!(re.is_match("foo123bar"));
56 1 : assert!(!re.is_match("foo"));
57 1 : let output = serde_json::to_string(&re).unwrap();
58 1 : assert_eq!(output, input);
59 1 : }
60 : }
|