1use std::{hash, ops::Deref};
3
4use regex::Regex;
5#[cfg(feature = "wasm")]
6use tsify::Tsify;
7
8#[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
10#[cfg_attr(feature = "wasm", derive(Tsify))]
11#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
12pub struct EncodableRegex(
13 #[serde(with = "serde_regex")]
14 #[cfg_attr(feature = "wasm", tsify(type = "RegExp"))]
15 Regex,
16);
17
18impl PartialEq for EncodableRegex {
19 fn eq(&self, other: &Self) -> bool {
20 self.0.as_str() == other.0.as_str()
21 }
22}
23
24impl hash::Hash for EncodableRegex {
25 fn hash<H: hash::Hasher>(&self, state: &mut H) {
26 self.0.as_str().hash(state);
27 }
28}
29
30impl EncodableRegex {
31 pub fn new<S: AsRef<str>>(pattern: S) -> Result<Self, regex::Error> {
33 Regex::new(pattern.as_ref()).map(EncodableRegex)
34 }
35}
36
37impl From<Regex> for EncodableRegex {
38 fn from(regex: Regex) -> Self {
39 EncodableRegex(regex)
40 }
41}
42impl AsRef<Regex> for EncodableRegex {
43 fn as_ref(&self) -> &Regex {
44 &self.0
45 }
46}
47
48impl Deref for EncodableRegex {
49 type Target = Regex;
50
51 fn deref(&self) -> &Self::Target {
52 &self.0
53 }
54}
55
56#[cfg(feature = "bincode")]
57mod bincode_impls {
58 use super::{EncodableRegex, Regex};
59
60 impl bincode::Encode for EncodableRegex {
61 fn encode<E: bincode::enc::Encoder>(
62 &self,
63 encoder: &mut E,
64 ) -> Result<(), bincode::error::EncodeError> {
65 self.0.as_str().encode(encoder)
66 }
67 }
68
69 impl<Context> bincode::Decode<Context> for EncodableRegex {
70 fn decode<D: bincode::de::Decoder>(
71 decoder: &mut D,
72 ) -> Result<Self, bincode::error::DecodeError> {
73 let regex_str: String = bincode::Decode::decode(decoder)?;
74 Regex::new(®ex_str)
75 .map(EncodableRegex)
76 .map_err(|_| bincode::error::DecodeError::Other("Invalid regex"))
77 }
78 }
79 bincode::impl_borrow_decode!(EncodableRegex);
80}