ordered_hash_map/
set.rs

1use core::borrow::Borrow;
2use core::fmt;
3use core::hash::{BuildHasher, Hash};
4use core::ops::Index;
5
6pub use hashbrown::DefaultHashBuilder;
7pub use hashbrown::TryReserveError;
8
9use crate::ordered_map;
10
11mod iter;
12pub use iter::{Drain, IntoIter, Iter};
13
14#[cfg(feature = "serde")]
15mod serde;
16
17/// A hash set which preserves the order of insertion.
18///
19/// Backed by [`hashbrown`] and its default hashing algorithm, currently [`AHash`]. The hashing
20/// algorithm can be changed on a per-map basis with [`with_hasher`] and [`with_capacity_and_hasher`].
21/// More details on hashing algorithms and why AHash was selected in the [`hashbrown`] crate.
22///
23/// To switch to the same hasher as [`HashMap`] use [`RandomState`]. This will switch to SipHash, a
24/// HashDos resistant algorithm but it may be slower in some cases.
25///
26/// Being backed by a HashMap, this container has all the same requirements on its keys as
27/// [`HashMap`]. Specifically, Keys must implement [`Eq`] and [`Hash`]. You can typically derive
28/// these for types with `#[derive(PartialEq, Eq, hash)]`. If you implement these yourself you must
29/// ensure the following holds:
30///
31/// ```text
32/// k1 == k2 -> hash(k1) == hash(k2)
33/// ```
34/// You are also responsible to ensure Keys do not mutate such that their hash can change while in
35/// the map. For more information, check [`HashMap`].
36///
37/// This container has some additional memory overhead on top of its backing HashMap. [`OrderedHashSet`]
38/// holds two pointers to maintain the linked list. Each Value inserted has the overhead of three pointers, one for the key
39/// and two for the linked list properties.
40///
41/// [`AHash`]: https://crates.io/crates/ahash
42/// [`hashbrown`]: https://crates.io/crates/hashbrown
43/// [`with_hasher`]: Self::with_hasher
44/// [`with_capacity_and_hasher`]: Self::with_capacity_and_hasher
45/// [`HashMap`]: std::collections::HashMap
46/// [`RandomState`]: std::collections::hash_map::RandomState
47pub struct OrderedHashSet<T, S = DefaultHashBuilder> {
48    map: ordered_map::OrderedHashMap<T, (), S>,
49}
50
51impl<T, S> fmt::Debug for OrderedHashSet<T, S>
52where
53    T: fmt::Debug,
54{
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        f.debug_list().entries(self.iter()).finish()
57    }
58}
59
60impl<T, S> Clone for OrderedHashSet<T, S>
61where
62    T: Hash + Eq + Clone,
63    S: BuildHasher + Clone,
64{
65    fn clone(&self) -> Self {
66        Self {
67            map: self.map.clone(),
68        }
69    }
70}
71
72impl<T, S> Default for OrderedHashSet<T, S>
73where
74    S: Default,
75{
76    fn default() -> Self {
77        Self {
78            map: Default::default(),
79        }
80    }
81}
82
83impl<T> OrderedHashSet<T, DefaultHashBuilder> {
84    /// Create an empty set.
85    ///
86    /// Capacity is 0 so the set will not allocated until inserted into.
87    /// ```
88    /// use ordered_hash_map::OrderedHashSet;
89    /// let set = OrderedHashSet::<i32>::new();
90    /// ```
91    pub fn new() -> Self {
92        Self::default()
93    }
94
95    /// Create an empty set with at least the specified capacity.
96    ///
97    /// The map will allocate if capacity is nonzero.
98    /// ```
99    /// use ordered_hash_map::OrderedHashSet;
100    /// let set = OrderedHashSet::<i32>::with_capacity(10);
101    /// assert!(set.capacity() >= 10)
102    /// ```
103    pub fn with_capacity(capacity: usize) -> Self {
104        Self {
105            map: ordered_map::OrderedHashMap::with_capacity(capacity),
106        }
107    }
108
109    /// Returns a draining iterator over the elements in insertion order.
110    ///
111    /// # Performance
112    /// This iterator visits each element once instead of each bucket once. This iterator is O(len)
113    /// which a usual map iterator is O(capacity) and may visit empty buckets.
114    /// ```
115    /// # use ordered_hash_map::OrderedHashSet;
116    /// let mut set: OrderedHashSet<i32> = [1i32, 2, 3, 4, 5].iter().collect();
117    /// assert_eq!(set.drain().next(), Some(1));
118    /// assert!(set.is_empty());
119    /// ```
120    pub fn drain(&mut self) -> Drain<'_, T> {
121        Drain {
122            inner: self.map.drain(),
123        }
124    }
125}
126
127impl<T, S> OrderedHashSet<T, S> {
128    /// Returns a draining iterator over the elements in insertion order.
129    ///
130    /// # Performance
131    /// This iterator visits each element once instead of each bucket once. This iterator is O(len)
132    /// which a usual map iterator is O(capacity) and may visit empty buckets.
133    /// ```
134    /// # use ordered_hash_map::OrderedHashSet;
135    /// use std::collections::hash_map::RandomState;
136    ///
137    /// let rs = RandomState::new();
138    /// let set = OrderedHashSet::<i32, _>::with_hasher(rs);
139    /// ```
140    pub const fn with_hasher(hash_builder: S) -> Self {
141        Self {
142            map: ordered_map::OrderedHashMap::with_hasher(hash_builder),
143        }
144    }
145
146    /// Create an empty set with the given capacity and which will use the given hasher.
147    ///
148    /// The map will allocate if capacity is nonzero.
149    /// ```no_run
150    /// # use ordered_hash_map::OrderedHashSet;
151    /// use std::collections::hash_map::RandomState;
152    ///
153    /// let rs = RandomState::new();
154    /// let set = OrderedHashSet::<i32, _>::with_capacity_and_hasher(10, rs);
155    /// assert!(set.capacity() >= 10)
156    /// ```
157    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
158        Self {
159            map: ordered_map::OrderedHashMap::with_capacity_and_hasher(capacity, hash_builder),
160        }
161    }
162
163    /// Returns a reference to the sets hasher.
164    /// ```
165    /// # use ordered_hash_map::OrderedHashSet;
166    /// use std::collections::hash_map::RandomState;
167    ///
168    /// let rs = RandomState::new();
169    /// let set = OrderedHashSet::<i32, _>::with_hasher(rs);
170    /// let rs: &RandomState = set.hasher();
171    /// ```
172    pub fn hasher(&self) -> &S {
173        self.map.hasher()
174    }
175
176    /// The number of elements the set can hold without reallocating.
177    pub fn capacity(&self) -> usize {
178        self.map.capacity()
179    }
180
181    /// The number of elements currently held in the set.
182    pub fn len(&self) -> usize {
183        self.map.len()
184    }
185
186    /// Returns whether the set is empty.
187    pub fn is_empty(&self) -> bool {
188        self.map.is_empty()
189    }
190
191    /// Removes all values from the set.
192    pub fn clear(&mut self) {
193        self.map.clear();
194    }
195
196    /// Returns an iterator over the elements in insertion order.
197    ///
198    /// # Performance
199    /// This iterator visits each element once instead of each bucket once. This iterator is O(len)
200    /// which a usual map iterator is O(capacity) and may visit empty buckets.
201    pub fn iter(&self) -> Iter<'_, T> {
202        self.into_iter()
203    }
204}
205
206impl<T, S> OrderedHashSet<T, S>
207where
208    T: Eq + Hash,
209    S: BuildHasher,
210{
211    /// Insert a new element into the set. Returns whether the key already existed.
212    /// ```
213    /// # use ordered_hash_map::OrderedHashSet;
214    /// let mut set = OrderedHashSet::<i32>::new();
215    /// assert!(!set.insert(4));
216    /// assert!(set.insert(4));
217    /// ```
218    pub fn insert(&mut self, value: T) -> bool {
219        self.map.insert(value, ()).is_some()
220    }
221
222    /// Returns a reference to the value stored in the set.
223    /// ```
224    /// # use ordered_hash_map::OrderedHashSet;
225    /// let mut set = OrderedHashSet::<String>::new();
226    /// set.insert("A".to_string());
227    /// // Stored as String but can use &str to get
228    /// assert_eq!(set.get("A"), Some(&String::from("A")));
229    /// ```
230    pub fn get<Q>(&self, value: &Q) -> Option<&T>
231    where
232        T: Borrow<Q>,
233        Q: Hash + Eq + ?Sized,
234    {
235        self.map.get_key_value(value).map(|(x, _)| x)
236    }
237
238    /// Remove an element from the set, returning whether or not the element existed.
239    pub fn remove<Q>(&mut self, value: &Q) -> bool
240    where
241        T: Borrow<Q>,
242        Q: Hash + Eq + ?Sized,
243    {
244        self.map.remove(value).is_some()
245    }
246
247    /// Remove and return an element from the set
248    pub fn take<Q>(&mut self, value: &Q) -> Option<T>
249    where
250        T: Borrow<Q>,
251        Q: Hash + Eq + ?Sized,
252    {
253        self.map.remove_entry(value).map(|(x, _)| x)
254    }
255
256    /// Check if the set contains this key.
257    pub fn contains<Q>(&mut self, value: &Q) -> bool
258    where
259        T: Borrow<Q>,
260        Q: Hash + Eq + ?Sized,
261    {
262        self.map.contains_key(value)
263    }
264
265    /// Reserves capacity for at least `additional` more elements.
266    ///
267    /// # Panics
268    /// Panics if the new size would overflow a usize.
269    pub fn reserve(&mut self, additional: usize) {
270        self.map.reserve(additional);
271    }
272
273    /// Tries to reserve capacity for at least `additional` more elements.
274    ///
275    /// # Errors
276    /// Returns an error if the new size would overflow a usize.
277    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
278        self.map.try_reserve(additional)
279    }
280
281    /// Shrinks the map as much as possible. May leave some space in accordance with the resize
282    /// policy.
283    pub fn shrink_to_fit(&mut self) {
284        self.map.shrink_to_fit();
285    }
286
287    /// Shrinks the map down to a lower limit. May leave some space in accordance with the resize
288    /// policy.
289    pub fn shrink_to(&mut self, min_capacity: usize) {
290        self.map.shrink_to(min_capacity);
291    }
292
293    /// Removes and returns the most recently inserted value, if there is one.
294    pub fn pop_back(&mut self) -> Option<T> {
295        self.map.pop_back_entry().map(|(x, _)| x)
296    }
297
298    /// Returns the most recently inserted value, if there is one
299    pub fn back(&self) -> Option<&T> {
300        self.map.back_entry().map(|(x, _)| x)
301    }
302
303    /// Remove and return the least recently inserted value, if there is one.
304    pub fn pop_front(&mut self) -> Option<T> {
305        self.map.pop_front_entry().map(|(x, _)| x)
306    }
307
308    /// Returns the most recently inserted value, if there is one
309    pub fn front(&self) -> Option<&T> {
310        self.map.front_entry().map(|(x, _)| x)
311    }
312
313    /// Move an element to the front of the list
314    pub fn move_to_front<Q>(&mut self, key: &Q)
315    where
316        T: Borrow<Q>,
317        Q: Hash + Eq + ?Sized,
318    {
319        self.map.move_to_front(key);
320    }
321
322    /// Move and element to the back of the list
323    pub fn move_to_back<Q>(&mut self, key: &Q)
324    where
325        T: Borrow<Q>,
326        Q: Hash + Eq + ?Sized,
327    {
328        self.map.move_to_back(key);
329    }
330}
331
332impl<T, S> PartialEq for OrderedHashSet<T, S>
333where
334    T: Eq + Hash,
335    S: BuildHasher,
336{
337    fn eq(&self, other: &OrderedHashSet<T, S>) -> bool {
338        self.map.eq(&other.map)
339    }
340}
341
342impl<T, S> Eq for OrderedHashSet<T, S>
343where
344    T: Eq + Hash,
345    S: BuildHasher,
346{
347}
348
349impl<T, Q, S> Index<&Q> for OrderedHashSet<T, S>
350where
351    T: Eq + Hash + Borrow<Q>,
352    Q: Eq + Hash + ?Sized,
353    S: BuildHasher,
354{
355    type Output = T;
356
357    fn index(&self, key: &Q) -> &T {
358        self.get(key).expect("no entry found for key")
359    }
360}
361
362#[cfg(test)]
363mod tests {
364    use super::OrderedHashSet;
365    #[test]
366    fn default() {
367        let set = OrderedHashSet::<i32>::new();
368        assert_eq!(set.len(), 0);
369        assert_eq!(set.iter().size_hint(), (0, Some(0)));
370        assert_eq!(set.iter().next(), None);
371        assert_eq!(set.iter().next_back(), None);
372    }
373
374    #[test]
375    fn clone() {
376        let set: OrderedHashSet<i32> = [1, 2, 3, 4].into_iter().collect();
377        let set_clone = set.clone();
378
379        assert_eq!(set, set_clone);
380        assert_eq!(format!("{:?}", set), format!("{:?}", set_clone));
381
382        set.iter()
383            .zip(set_clone.iter())
384            .for_each(|(val, val_clone)| assert_eq!(val, val_clone));
385
386        assert_eq!(set.len(), 4);
387
388        set.iter()
389            .rev()
390            .zip(set_clone.iter().rev())
391            .for_each(|(val, val_clone)| assert_eq!(val, val_clone));
392    }
393
394    #[test]
395    fn sizes() {
396        let mut set: OrderedHashSet<i32> = [1, 2, 3, 4].into_iter().collect();
397        assert_eq!(set.len(), 4);
398        assert!(!set.is_empty());
399
400        let mut drain = set.drain();
401        assert_eq!(drain.next(), Some(1));
402        assert_eq!(drain.next_back(), Some(4));
403
404        drop(drain); // Drop without consuming all of it
405
406        assert_eq!(set.len(), 0);
407        assert!(set.is_empty());
408
409        let mut set: OrderedHashSet<i32> = [1, 2, 3, 4].into_iter().collect();
410        set.clear();
411        assert_eq!(set.len(), 0);
412        assert!(set.is_empty());
413    }
414
415    #[test]
416    fn insert_remove_ops() {
417        let mut set = OrderedHashSet::<i32>::with_capacity(10);
418        assert!(set.capacity() >= 10);
419        set.reserve(15);
420        assert!(set.capacity() >= 25);
421
422        // First try on empty sets
423        assert!(!set.remove(&1));
424        assert!(set.get(&2).is_none());
425        assert!(set.take(&3).is_none());
426        assert!(set.back().is_none());
427        assert!(set.pop_back().is_none());
428        assert!(set.front().is_none());
429        assert!(set.pop_front().is_none());
430
431        set.move_to_front(&1); // Don't crash on non existent element
432
433        let mut set: OrderedHashSet<i32> = [1, 2, 3, 4].into_iter().collect();
434        assert!(!set.contains(&5));
435        assert!(!set.insert(5)); // [1, 2, 3, 4, 5]
436        assert!(set.insert(5)); // no change
437        assert!(set.contains(&5));
438        assert!(set.remove(&1)); // [2, 3, 4, 5]
439        assert_eq!(set[&2], 2); // no change
440        assert_eq!(set.take(&3), Some(3)); // [2, 4, 5]
441        assert_eq!(set.back(), Some(&5)); // no change
442        assert_eq!(set.pop_back(), Some(5)); // [2, 4]
443        assert_eq!(set.front(), Some(&2)); // no change
444        assert_eq!(set.pop_front(), Some(2)); // [4]
445        assert_eq!(set.get(&4), set.back());
446        assert_eq!(set.front(), set.back());
447    }
448
449    #[test]
450    fn move_to() {
451        let mut set: OrderedHashSet<i32> = [1, 2, 3].into_iter().collect();
452        set.move_to_front(&2);
453        assert_eq!(set, [2, 1, 3].into_iter().collect());
454        set.move_to_back(&2);
455        assert_eq!(set, [1, 3, 2].into_iter().collect());
456    }
457}