ckb_util/
linked_hash_set.rs

1//! A `HashSet` wrapper that holds value in insertion order.
2
3use linked_hash_map::{self, Keys, LinkedHashMap};
4use std::collections::hash_map::DefaultHasher;
5use std::hash::{BuildHasher, BuildHasherDefault, Hash};
6use std::iter::Extend;
7
8type DefaultBuildHasher = BuildHasherDefault<DefaultHasher>;
9
10/// A HashSet that holds elements in insertion order.
11///
12/// ## Examples
13///
14/// ```
15/// use ckb_util::LinkedHashSet;
16///
17/// let mut set = LinkedHashSet::new();
18/// set.insert(2);
19/// set.insert(1);
20/// set.insert(3);
21///
22/// let items: Vec<i32> = set.iter().copied().collect();
23/// assert_eq!(items, [2, 1, 3]);
24/// ```
25pub struct LinkedHashSet<T, S = DefaultBuildHasher> {
26    map: LinkedHashMap<T, (), S>,
27}
28
29pub struct Iter<'a, K: 'a> {
30    iter: Keys<'a, K, ()>,
31}
32
33impl<K> Clone for Iter<'_, K> {
34    fn clone(&self) -> Self {
35        Iter {
36            iter: self.iter.clone(),
37        }
38    }
39}
40
41impl<'a, K> Iterator for Iter<'a, K>
42where
43    K: Eq + Hash,
44{
45    type Item = &'a K;
46
47    fn next(&mut self) -> Option<&'a K> {
48        self.iter.next()
49    }
50    fn size_hint(&self) -> (usize, Option<usize>) {
51        self.iter.size_hint()
52    }
53}
54pub struct Difference<'a, T: 'a, S: 'a> {
55    // iterator of the first set
56    iter: Iter<'a, T>,
57    // the second set
58    other: &'a LinkedHashSet<T, S>,
59}
60
61impl<T, S> Clone for Difference<'_, T, S> {
62    fn clone(&self) -> Self {
63        Difference {
64            iter: self.iter.clone(),
65            ..*self
66        }
67    }
68}
69
70impl<'a, T, S> Iterator for Difference<'a, T, S>
71where
72    T: Eq + Hash,
73    S: BuildHasher,
74{
75    type Item = &'a T;
76
77    fn next(&mut self) -> Option<&'a T> {
78        loop {
79            let elt = self.iter.next()?;
80            if !self.other.contains(elt) {
81                return Some(elt);
82            }
83        }
84    }
85
86    fn size_hint(&self) -> (usize, Option<usize>) {
87        let (_, upper) = self.iter.size_hint();
88        (0, upper)
89    }
90}
91
92impl<T: Hash + Eq> LinkedHashSet<T, DefaultBuildHasher> {
93    /// Creates a linked hash set.
94    ///
95    /// ## Examples
96    ///
97    /// ```
98    /// use ckb_util::LinkedHashSet;
99    /// let set: LinkedHashSet<i32> = LinkedHashSet::new();
100    /// ```
101    pub fn new() -> LinkedHashSet<T, DefaultBuildHasher> {
102        LinkedHashSet {
103            map: LinkedHashMap::default(),
104        }
105    }
106
107    /// Creates an empty linked hash map with the given initial capacity.
108    ///
109    /// ## Examples
110    ///
111    /// ```
112    /// use ckb_util::LinkedHashSet;
113    /// let set: LinkedHashSet<i32> = LinkedHashSet::with_capacity(42);
114    /// ```
115    pub fn with_capacity(capacity: usize) -> LinkedHashSet<T, DefaultBuildHasher> {
116        LinkedHashSet {
117            map: LinkedHashMap::with_capacity_and_hasher(capacity, Default::default()),
118        }
119    }
120}
121
122impl<T, S> LinkedHashSet<T, S>
123where
124    T: Eq + Hash,
125    S: BuildHasher,
126{
127    /// Returns `true` if the set contains a value.
128    ///
129    /// ```
130    /// use ckb_util::LinkedHashSet;
131    ///
132    /// let mut set: LinkedHashSet<_> = LinkedHashSet::new();
133    /// set.insert(1);
134    /// set.insert(2);
135    /// set.insert(3);
136    /// assert_eq!(set.contains(&1), true);
137    /// assert_eq!(set.contains(&4), false);
138    /// ```
139    pub fn contains(&self, value: &T) -> bool {
140        self.map.contains_key(value)
141    }
142
143    /// Returns the number of elements the set can hold without reallocating.
144    pub fn capacity(&self) -> usize {
145        self.map.capacity()
146    }
147
148    /// Returns the number of elements in the set.
149    pub fn len(&self) -> usize {
150        self.map.len()
151    }
152
153    /// Returns `true` if the set contains no elements.
154    pub fn is_empty(&self) -> bool {
155        self.map.is_empty()
156    }
157
158    /// Adds a value to the set.
159    ///
160    /// If the set did not have this value present, true is returned.
161    ///
162    /// If the set did have this value present, false is returned.
163    pub fn insert(&mut self, value: T) -> bool {
164        self.map.insert(value, ()).is_none()
165    }
166
167    /// Gets an iterator visiting all elements in insertion order.
168    ///
169    /// The iterator element type is `&'a T`.
170    pub fn iter(&self) -> Iter<T> {
171        Iter {
172            iter: self.map.keys(),
173        }
174    }
175
176    /// Visits the values representing the difference, i.e., the values that are in `self` but not in `other`.
177    pub fn difference<'a>(&'a self, other: &'a LinkedHashSet<T, S>) -> Difference<'a, T, S> {
178        Difference {
179            iter: self.iter(),
180            other,
181        }
182    }
183
184    /// Clears the set of all value.
185    pub fn clear(&mut self) {
186        self.map.clear();
187    }
188}
189
190impl<T: Hash + Eq> Default for LinkedHashSet<T, DefaultBuildHasher> {
191    /// Creates an empty `HashSet<T>` with the `Default` value for the hasher.
192    fn default() -> LinkedHashSet<T, DefaultBuildHasher> {
193        LinkedHashSet {
194            map: LinkedHashMap::default(),
195        }
196    }
197}
198
199impl<T, S> Extend<T> for LinkedHashSet<T, S>
200where
201    T: Eq + Hash,
202    S: BuildHasher,
203{
204    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
205        self.map.extend(iter.into_iter().map(|k| (k, ())));
206    }
207}
208
209impl<'a, T, S> IntoIterator for &'a LinkedHashSet<T, S>
210where
211    T: Eq + Hash,
212    S: BuildHasher,
213{
214    type Item = &'a T;
215    type IntoIter = Iter<'a, T>;
216
217    fn into_iter(self) -> Iter<'a, T> {
218        self.iter()
219    }
220}
221
222impl<T, S> IntoIterator for LinkedHashSet<T, S>
223where
224    T: Eq + Hash,
225    S: BuildHasher,
226{
227    type Item = T;
228    type IntoIter = IntoIter<T>;
229
230    fn into_iter(self) -> IntoIter<T> {
231        IntoIter {
232            iter: self.map.into_iter(),
233        }
234    }
235}
236
237pub struct IntoIter<K> {
238    iter: linked_hash_map::IntoIter<K, ()>,
239}
240
241impl<K> Iterator for IntoIter<K> {
242    type Item = K;
243
244    fn next(&mut self) -> Option<K> {
245        self.iter.next().map(|(k, _)| k)
246    }
247    fn size_hint(&self) -> (usize, Option<usize>) {
248        self.iter.size_hint()
249    }
250}
251
252impl<K> ExactSizeIterator for IntoIter<K> {
253    fn len(&self) -> usize {
254        self.iter.len()
255    }
256}