1use std::{
2 fmt::Debug,
3 hash::{BuildHasher, BuildHasherDefault, Hash},
4 marker::PhantomData,
5};
6
7use rustc_hash::FxHasher;
8use serde::{Deserialize, Serialize};
9use shrink_to_fit::ShrinkToFit;
10
11use crate::AutoMap;
12
13#[derive(Clone)]
14pub struct AutoSet<K, H = BuildHasherDefault<FxHasher>, const I: usize = 0> {
15 map: AutoMap<K, (), H, I>,
16}
17
18impl<K, H, const I: usize> Default for AutoSet<K, H, I> {
19 fn default() -> Self {
20 Self {
21 map: Default::default(),
22 }
23 }
24}
25
26impl<K: Debug, H, const I: usize> Debug for AutoSet<K, H, I> {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 f.debug_set().entries(self.iter()).finish()
29 }
30}
31
32impl<K> AutoSet<K, BuildHasherDefault<FxHasher>, 0> {
33 pub const fn new() -> Self {
35 Self {
36 map: AutoMap::new(),
37 }
38 }
39
40 pub fn with_capacity(capacity: usize) -> Self {
42 Self {
43 map: AutoMap::with_capacity(capacity),
44 }
45 }
46}
47
48impl<K, H: BuildHasher, const I: usize> AutoSet<K, H, I> {
49 pub const fn with_hasher() -> Self {
51 Self {
52 map: AutoMap::with_hasher(),
53 }
54 }
55
56 pub fn with_capacity_and_hasher(capacity: usize, hasher: H) -> Self {
58 Self {
59 map: AutoMap::with_capacity_and_hasher(capacity, hasher),
60 }
61 }
62
63 pub fn clear(&mut self) {
65 self.map.clear();
66 }
67}
68
69impl<K: Hash + Eq, H: BuildHasher + Default, const I: usize> AutoSet<K, H, I> {
70 pub fn insert(&mut self, key: K) -> bool {
72 self.map.insert(key, ()).is_none()
73 }
74
75 pub fn remove(&mut self, key: &K) -> bool {
77 self.map.remove(key).is_some()
78 }
79
80 pub fn extend(&mut self, iter: impl IntoIterator<Item = K>) {
82 self.map.extend(iter.into_iter().map(|item| (item, ())))
83 }
84
85 pub fn shrink_to_fit(&mut self) {
87 self.map.shrink_to_fit();
88 }
89
90 pub fn contains(&self, key: &K) -> bool {
92 self.map.contains_key(key)
93 }
94}
95
96impl<K, H, const I: usize> AutoSet<K, H, I> {
97 pub fn len(&self) -> usize {
99 self.map.len()
100 }
101
102 pub fn is_empty(&self) -> bool {
104 self.map.is_empty()
105 }
106
107 pub fn iter(&self) -> Iter<'_, K> {
109 Iter(self.map.iter())
110 }
111}
112
113impl<K, H, const I: usize> IntoIterator for AutoSet<K, H, I> {
114 type Item = K;
115 type IntoIter = IntoIter<K, I>;
116
117 fn into_iter(self) -> Self::IntoIter {
118 IntoIter(self.map.into_iter())
119 }
120}
121
122impl<'a, K, H, const I: usize> IntoIterator for &'a AutoSet<K, H, I> {
123 type Item = &'a K;
124 type IntoIter = Iter<'a, K>;
125
126 fn into_iter(self) -> Self::IntoIter {
127 self.iter()
128 }
129}
130
131pub struct Iter<'a, K>(super::map::Iter<'a, K, ()>);
132
133impl<'a, K> Iterator for Iter<'a, K> {
134 type Item = &'a K;
135
136 fn next(&mut self) -> Option<Self::Item> {
137 self.0.next().map(|(k, _)| k)
138 }
139
140 fn size_hint(&self) -> (usize, Option<usize>) {
141 self.0.size_hint()
142 }
143}
144
145impl<K> Clone for Iter<'_, K> {
146 fn clone(&self) -> Self {
147 Self(self.0.clone())
148 }
149}
150
151pub struct IntoIter<K, const I: usize>(super::map::IntoIter<K, (), I>);
152
153impl<K, const I: usize> Iterator for IntoIter<K, I> {
154 type Item = K;
155
156 fn next(&mut self) -> Option<Self::Item> {
157 self.0.next().map(|(k, _)| k)
158 }
159
160 fn size_hint(&self) -> (usize, Option<usize>) {
161 self.0.size_hint()
162 }
163}
164
165impl<K, H, const I: usize> Serialize for AutoSet<K, H, I>
166where
167 K: Serialize,
168 H: BuildHasher,
169{
170 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
171 serializer.collect_seq(self.iter())
172 }
173}
174
175impl<'de, K, H, const I: usize> Deserialize<'de> for AutoSet<K, H, I>
176where
177 K: Deserialize<'de> + Hash + Eq,
178 H: BuildHasher + Default,
179{
180 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
181 struct AutoSetVisitor<K, H, const I: usize>(PhantomData<AutoSet<K, H, I>>);
182
183 impl<'de, K, H, const I: usize> serde::de::Visitor<'de> for AutoSetVisitor<K, H, I>
184 where
185 K: Deserialize<'de> + Hash + Eq,
186 H: BuildHasher + Default,
187 {
188 type Value = AutoSet<K, H, I>;
189
190 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
191 formatter.write_str("a set")
192 }
193
194 fn visit_seq<A: serde::de::SeqAccess<'de>>(
195 self,
196 mut seq: A,
197 ) -> Result<Self::Value, A::Error> {
198 let mut set = if let Some(size) = seq.size_hint() {
199 AutoSet::with_capacity_and_hasher(size, H::default())
200 } else {
201 AutoSet::with_hasher()
202 };
203 while let Some(item) = seq.next_element()? {
204 set.insert(item);
205 }
206 Ok(set)
207 }
208 }
209
210 deserializer.deserialize_seq(AutoSetVisitor(std::marker::PhantomData))
211 }
212}
213
214impl<K: Eq + Hash, H: BuildHasher, const I: usize> PartialEq for AutoSet<K, H, I> {
215 fn eq(&self, other: &Self) -> bool {
216 self.map == other.map
217 }
218}
219
220impl<K: Eq + Hash, H: BuildHasher, const I: usize> Eq for AutoSet<K, H, I> {}
221
222impl<K, H, const I: usize> FromIterator<K> for AutoSet<K, H, I>
223where
224 K: Hash + Eq,
225 H: BuildHasher + Default,
226{
227 fn from_iter<T: IntoIterator<Item = K>>(iter: T) -> Self {
228 Self {
229 map: AutoMap::from_iter(iter.into_iter().map(|item| (item, ()))),
230 }
231 }
232}
233
234impl<K, H, const N: usize, const I: usize> From<[K; N]> for AutoSet<K, H, I>
235where
236 K: Hash + Eq,
237 H: BuildHasher + Default,
238{
239 fn from(array: [K; N]) -> Self {
240 Self::from_iter(array)
241 }
242}
243
244impl<K, H, const I: usize> ShrinkToFit for AutoSet<K, H, I>
245where
246 K: Eq + Hash,
247 H: BuildHasher + Default,
248{
249 fn shrink_to_fit(&mut self) {
250 self.map.shrink_to_fit();
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257 use crate::MAX_LIST_SIZE;
258
259 #[test]
260 fn test_auto_set() {
261 let mut set = AutoSet::new();
262 for i in 0..MAX_LIST_SIZE * 2 {
263 set.insert(i);
264 }
265 for i in 0..MAX_LIST_SIZE * 2 {
266 assert!(set.contains(&i));
267 }
268 assert!(!set.contains(&(MAX_LIST_SIZE * 2)));
269 for i in 0..MAX_LIST_SIZE * 2 {
270 assert!(!set.remove(&(MAX_LIST_SIZE * 2)));
271 assert!(set.remove(&i));
272 }
273 assert!(!set.remove(&(MAX_LIST_SIZE * 2)));
274 }
275}