1use std::hash::BuildHasher;
16
17use ahash::RandomState;
18use serde::{Deserialize, Serialize};
19
20pub fn escape_like_pattern(pattern: &str) -> String {
32 pattern
33 .chars()
34 .flat_map(|c| match c {
35 '\\' | '%' | '_' => vec!['\\', c],
36 _ => vec![c],
37 })
38 .collect::<String>()
39}
40
41#[derive(Debug)]
46pub struct FixedRandomState {
47 state: RandomState,
48}
49
50impl FixedRandomState {
51 const RANDOM_SEED_0: u64 = 0x517cc1b727220a95;
53 const RANDOM_SEED_1: u64 = 0x428a2f98d728ae22;
54 const RANDOM_SEED_2: u64 = 0x7137449123ef65cd;
55 const RANDOM_SEED_3: u64 = 0xb5c0fbcfec4d3b2f;
56
57 pub fn new() -> Self {
58 Self {
59 state: ahash::RandomState::with_seeds(
60 Self::RANDOM_SEED_0,
61 Self::RANDOM_SEED_1,
62 Self::RANDOM_SEED_2,
63 Self::RANDOM_SEED_3,
64 ),
65 }
66 }
67}
68
69impl Default for FixedRandomState {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl BuildHasher for FixedRandomState {
76 type Hasher = ahash::AHasher;
77
78 fn build_hasher(&self) -> Self::Hasher {
79 self.state.build_hasher()
80 }
81
82 fn hash_one<T: std::hash::Hash>(&self, x: T) -> u64 {
83 self.state.hash_one(x)
84 }
85}
86
87impl Serialize for FixedRandomState {
88 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89 where
90 S: serde::Serializer,
91 {
92 serializer.serialize_unit()
93 }
94}
95
96impl<'de> Deserialize<'de> for FixedRandomState {
97 fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
98 where
99 D: serde::Deserializer<'de>,
100 {
101 Ok(Self::new())
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn test_escape_like_pattern() {
111 assert_eq!(
112 escape_like_pattern("100%_some\\path"),
113 "100\\%\\_some\\\\path"
114 );
115 assert_eq!(escape_like_pattern(""), "");
116 assert_eq!(escape_like_pattern("hello"), "hello");
117 assert_eq!(escape_like_pattern("\\%_"), "\\\\\\%\\_");
118 assert_eq!(escape_like_pattern("%%__\\\\"), "\\%\\%\\_\\_\\\\\\\\");
119 assert_eq!(escape_like_pattern("abc123"), "abc123");
120 assert_eq!(escape_like_pattern("%_\\"), "\\%\\_\\\\");
121 assert_eq!(
122 escape_like_pattern("%%__\\\\another%string"),
123 "\\%\\%\\_\\_\\\\\\\\another\\%string"
124 );
125 assert_eq!(escape_like_pattern("foo%bar_"), "foo\\%bar\\_");
126 assert_eq!(escape_like_pattern("\\_\\%"), "\\\\\\_\\\\\\%");
127 }
128}