1use std::{
2 hash::{BuildHasher, Hash, Hasher, RandomState},
3 ops::{Deref, DerefMut},
4};
5
6macro_rules! make_hashable_set {
7 ($hash_set_impl:ident) => {
8 #[derive(Clone, Debug, Default)]
9 pub struct HashableSet<T, S = RandomState>($hash_set_impl<T, S>);
10
11 impl<T> HashableSet<T> {
12 pub fn new() -> Self {
13 Self($hash_set_impl::new())
14 }
15
16 pub fn with_capacity(capacity: usize) -> Self {
17 Self($hash_set_impl::with_capacity(capacity))
18 }
19 }
20
21 impl<T, S> HashableSet<T, S> {
22 pub fn with_hasher(hash_builder: S) -> Self {
23 Self($hash_set_impl::with_hasher(hash_builder))
24 }
25
26 pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
27 Self($hash_set_impl::with_capacity_and_hasher(
28 capacity,
29 hash_builder,
30 ))
31 }
32 }
33
34 impl<T, S> Deref for HashableSet<T, S> {
35 type Target = $hash_set_impl<T, S>;
36
37 fn deref(&self) -> &Self::Target {
38 &self.0
39 }
40 }
41
42 impl<T, S> DerefMut for HashableSet<T, S> {
43 fn deref_mut(&mut self) -> &mut Self::Target {
44 &mut self.0
45 }
46 }
47
48 impl<T, S> From<$hash_set_impl<T, S>> for HashableSet<T, S> {
49 fn from(value: $hash_set_impl<T, S>) -> Self {
50 Self(value)
51 }
52 }
53
54 impl<T, S> From<HashableSet<T, S>> for $hash_set_impl<T, S> {
55 fn from(value: HashableSet<T, S>) -> $hash_set_impl<T, S> {
56 value.0
57 }
58 }
59
60 impl<T, S, D> Hash for HashableSet<T, S>
61 where
62 T: Hash,
63 S: BuildHasher<Hasher = D>,
64 D: Hasher + Default,
65 {
66 fn hash<H: Hasher>(&self, state: &mut H) {
67 state.write_usize(self.len());
68
69 let hash = self
70 .iter()
71 .map(|t| {
72 let mut hasher = D::default();
73 t.hash(&mut hasher);
74 hasher.finish()
75 })
76 .fold(0, u64::wrapping_add);
77
78 state.write_u64(hash);
79 }
80 }
81
82 impl<T, S> PartialEq for HashableSet<T, S>
83 where
84 T: Eq + Hash,
85 S: BuildHasher,
86 {
87 fn eq(&self, other: &Self) -> bool {
88 self.0 == other.0
89 }
90 }
91
92 impl<T, S> Eq for HashableSet<T, S>
93 where
94 T: Eq + Hash,
95 S: BuildHasher,
96 {
97 }
98
99 #[cfg(feature = "serde")]
100 impl<T, S> serde::Serialize for HashableSet<T, S>
101 where
102 $hash_set_impl<T, S>: serde::Serialize,
103 {
104 fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
105 where
106 Ser: serde::Serializer,
107 {
108 self.0.serialize(serializer)
109 }
110 }
111
112 #[cfg(feature = "serde")]
113 impl<'de, T, S> serde::Deserialize<'de> for HashableSet<T, S>
114 where
115 $hash_set_impl<T, S>: serde::Deserialize<'de>,
116 {
117 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
118 where
119 D: serde::Deserializer<'de>,
120 {
121 Ok(Self($hash_set_impl::deserialize(deserializer)?))
122 }
123 }
124 };
125}
126
127use std::collections::HashSet;
128make_hashable_set!(HashSet);
129
130#[cfg(test)]
131pub(crate) mod tests {
132 use std::hash::BuildHasherDefault;
133
134 use super::*;
135
136 use crate::map::tests::*;
137
138 #[test]
139 fn insertion_order_random_state() {
140 insertion_order::<RandomState, _>()
141 }
142
143 #[test]
144 fn insertion_order_fx_build_hasher() {
145 insertion_order::<fxhash::FxBuildHasher, _>()
146 }
147
148 #[test]
149 fn insertion_order_fnv_build_hasher() {
150 insertion_order::<fnv::FnvBuildHasher, _>()
151 }
152
153 #[test]
154 fn insertion_order_ahash_build_hasher() {
155 insertion_order::<BuildHasherDefault<ahash::AHasher>, _>()
156 }
157
158 fn insertion_order<B: BuildHasher<Hasher = H> + Default, H: Hasher + Default>() {
159 let values = generate_random_values::<i32, 128>();
160 let values_shuffled = shuffle(&values);
161 let values_other = generate_random_values::<i32, 128>();
162
163 assert_ne!(values, values_shuffled);
164 assert_ne!(values, values_other);
165 assert_ne!(values_shuffled, values_other);
166
167 let mut a = HashableSet::<_, B>::default();
168 a.extend(values.iter().copied());
169 let mut b = HashableSet::<_, B>::default();
170 b.extend(values_shuffled.iter().copied());
171 let mut c = HashableSet::<_, B>::default();
172 c.extend(values_other.iter().copied());
173
174 assert_hash_eq(&a, &b);
175 assert_hash_ne(&a, &c);
176 assert_hash_ne(&b, &c)
177 }
178}