json_predicate/
regex.rs

1use std::marker::PhantomData;
2use std::str::FromStr;
3
4use regex::Regex as LibRegex;
5use serde::de::{self, Deserialize, Deserializer, Visitor};
6use serde::Serialize;
7
8/// A new type wrapping a `[regex::Regex]` with:
9///
10/// - Eq
11/// - PartialEq
12/// - Serialize
13/// - Deserialize
14#[derive(Clone, Debug)]
15pub struct Regex(LibRegex);
16
17impl AsRef<LibRegex> for Regex {
18    fn as_ref(&self) -> &LibRegex {
19        &self.0
20    }
21}
22
23impl From<LibRegex> for Regex {
24    fn from(value: LibRegex) -> Self {
25        Self(value)
26    }
27}
28
29impl From<Regex> for LibRegex {
30    fn from(value: Regex) -> Self {
31        value.0
32    }
33}
34
35impl PartialEq for Regex {
36    fn eq(&self, other: &Self) -> bool {
37        self.0.as_str() == other.0.as_str()
38    }
39}
40
41impl Eq for Regex {}
42
43impl Serialize for Regex {
44    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45    where
46        S: serde::Serializer,
47    {
48        serializer.serialize_str(self.0.as_str())
49    }
50}
51
52impl<'de> Deserialize<'de> for Regex {
53    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
54    where
55        D: Deserializer<'de>,
56    {
57        struct VisitorRegex<'de> {
58            marker: PhantomData<Regex>,
59            lifetime: PhantomData<&'de ()>,
60        }
61
62        impl<'de> Visitor<'de> for VisitorRegex<'de> {
63            type Value = Regex;
64            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
65                formatter.write_str("Regex")
66            }
67
68            #[inline]
69            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
70            where
71                E: de::Error,
72            {
73                let inner_regex =
74                    LibRegex::from_str(v).map_err(|err| serde::de::Error::custom(err))?;
75
76                Ok(Regex(inner_regex))
77            }
78        }
79
80        Deserializer::deserialize_str(
81            deserializer,
82            VisitorRegex {
83                marker: PhantomData::<Regex>,
84                lifetime: PhantomData,
85            },
86        )
87    }
88}