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#[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}