quickphf/
set.rs

1//! An immutable set constructed at compile time with perfect hashing.
2use core::hash::Hash;
3
4// TODO: Debug impls
5
6use crate::RawPhfMap;
7
8/// An immutable set constructed at compile time with perfect hashing.
9#[derive(Debug)]
10pub struct PhfSet<K: 'static> {
11    raw_map: RawPhfMap<K, K>,
12}
13
14impl<K> PhfSet<K> {
15    #[doc(hidden)]
16    /// This function is public because it is used by `quickphf_codegen` to
17    /// instantiate the set—users should never directly write calls to it.
18    pub const fn new(
19        seed: u64,
20        pilots_table: &'static [u16],
21        elements: &'static [K],
22        free: &'static [u32],
23    ) -> PhfSet<K> {
24        PhfSet {
25            raw_map: RawPhfMap::new(seed, pilots_table, elements, free),
26        }
27    }
28}
29
30impl<K> PhfSet<K> {
31    /// Returns the number of elements in the set.
32    ///   
33    /// # Examples
34    ///
35    /// ```
36    /// use quickphf::examples::*;
37    ///
38    /// assert_eq!(EVEN_DIGITS.len(), 5);
39    /// assert_eq!(EMPTY_SET.len(), 0);
40    /// ```
41    pub const fn len(&self) -> usize {
42        self.raw_map.len()
43    }
44
45    /// Returns `true` if the set does not contain any elements.
46    ///   
47    /// # Examples
48    ///
49    /// ```
50    /// use quickphf::examples::*;
51    ///
52    /// assert!(!DIGITS.is_empty());
53    /// assert!(EMPTY_SET.is_empty());
54    /// ```
55    pub const fn is_empty(&self) -> bool {
56        self.len() == 0
57    }
58
59    /// Returns an iterator over the elements of the set in no particular order.
60    ///   
61    /// # Examples
62    ///
63    /// ```
64    /// use quickphf::examples::*;
65    ///
66    /// let mut items = EVEN_DIGITS.iter().copied().collect::<Vec<_>>();
67    /// items.sort();
68    ///
69    /// assert_eq!(&items, &[0, 2, 4, 6, 8]);
70    /// ```
71    pub fn iter(&self) -> Iter<'_, K> {
72        Iter {
73            iter: self.raw_map.iter(),
74        }
75    }
76}
77
78impl<K: Eq + Hash> PhfSet<K> {
79    /// Returns `true` if the set contains the given element.
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// use quickphf::examples::*;
85    ///
86    /// assert!(PRIME_DIGITS.contains(&2));
87    /// assert!(!PRIME_DIGITS.contains(&1));
88    /// ```
89    pub fn contains(&self, element: &K) -> bool {
90        self.get(element).is_some()
91    }
92
93    /// Returns a reference to the copy of the element stored in the set, if
94    /// present.
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// use quickphf::examples::*;
100    ///
101    /// assert_eq!(EVEN_DIGITS.get(&2), Some(&2));
102    /// assert_eq!(EVEN_DIGITS.get(&3), None);
103    /// ```
104    pub fn get(&self, element: &K) -> Option<&K> {
105        if self.is_empty() {
106            return None;
107        }
108
109        let result = self.raw_map.get(element);
110        if result == element {
111            Some(result)
112        } else {
113            None
114        }
115    }
116
117    /// Returns an iterator over the set difference in no particular order.
118    ///
119    /// The iterator yields all items that are in `self` but not in `other`.
120    ///
121    /// # Examples
122    ///
123    /// ```
124    /// use quickphf::examples::*;
125    ///
126    /// let mut difference = EVEN_DIGITS
127    ///     .difference(&PRIME_DIGITS)
128    ///     .copied()
129    ///     .collect::<Vec<_>>();
130    /// difference.sort();
131    ///
132    /// assert_eq!(&difference, &[0, 4, 6, 8]);
133    /// ```
134    pub fn difference<'a>(&'a self, other: &'a PhfSet<K>) -> Difference<'a, K> {
135        Difference {
136            iter: self.iter(),
137            other,
138        }
139    }
140
141    /// Returns an iterator over the intersection in no particular order.
142    ///
143    /// The iterator yields all items that are in both `self` and `other`.
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// use quickphf::examples::*;
149    ///
150    /// let mut intersection = PRIME_DIGITS.intersection(&EVEN_DIGITS);
151    ///
152    /// assert_eq!(intersection.next(), Some(&2));
153    /// assert!(intersection.next().is_none());
154    /// ```
155    pub fn intersection<'a>(&'a self, other: &'a PhfSet<K>) -> Intersection<'a, K> {
156        Intersection {
157            iter: self.iter(),
158            other,
159        }
160    }
161
162    /// Returns an iterator over the symmetric difference of the two sets in no particular order.
163    ///
164    /// The iterator yields all items that are in `self` but not in `other`, or vice versa.
165    ///
166    /// # Examples
167    ///
168    /// ```
169    /// use quickphf::examples::*;
170    ///
171    /// let mut symmetric_difference = PRIME_DIGITS
172    ///     .symmetric_difference(&EVEN_DIGITS)
173    ///     .copied()
174    ///     .collect::<Vec<_>>();
175    /// symmetric_difference.sort();
176    ///
177    /// assert_eq!(&symmetric_difference, &[0, 3, 4, 5, 6, 7, 8]);
178    /// ```
179    pub fn symmetric_difference<'a>(&'a self, other: &'a PhfSet<K>) -> SymmetricDifference<'a, K> {
180        SymmetricDifference {
181            iter: self.difference(other).chain(other.difference(self)),
182        }
183    }
184
185    /// Returns an iterator over the union in no particular order.
186    ///
187    /// The iterator yields all items that are in `self` or `other`.
188    ///
189    /// # Examples
190    ///
191    /// ```
192    /// use quickphf::examples::*;
193    ///
194    /// let mut union = PRIME_DIGITS
195    ///     .union(&EVEN_DIGITS)
196    ///     .copied()
197    ///     .collect::<Vec<_>>();
198    /// union.sort();
199    ///
200    /// assert_eq!(&union, &[0, 2, 3, 4, 5, 6, 7, 8]);
201    /// ```
202    pub fn union<'a>(&'a self, other: &'a PhfSet<K>) -> Union<'a, K> {
203        Union {
204            iter: self.iter().chain(other.difference(self)),
205        }
206    }
207
208    /// Returns `true` if `self` and `other` have no elements in common.
209    ///
210    /// # Examples
211    ///
212    /// ```
213    /// use quickphf::examples::*;
214    ///
215    /// assert!(!EVEN_DIGITS.is_disjoint(&PRIME_DIGITS));
216    /// ```
217    pub fn is_disjoint(&self, other: &PhfSet<K>) -> bool {
218        self.intersection(other).next().is_none()
219    }
220
221    /// Returns `true` if there are no elements in `self` that are not in `other` as well.
222    ///
223    /// # Examples
224    ///
225    /// ```
226    /// use quickphf::examples::*;
227    ///
228    /// assert!(EVEN_DIGITS.is_subset(&DIGITS));
229    /// ```
230    pub fn is_subset(&self, other: &PhfSet<K>) -> bool {
231        self.difference(other).next().is_none()
232    }
233
234    /// Returns `true` if there are no elements of `other` that are not in `self`.
235    ///
236    /// # Examples
237    ///
238    /// ```
239    /// use quickphf::examples::*;
240    ///
241    /// assert!(DIGITS.is_superset(&EVEN_DIGITS));
242    /// ```
243    pub fn is_superset(&self, other: &PhfSet<K>) -> bool {
244        other.is_subset(self)
245    }
246}
247
248impl<'a, K> IntoIterator for &'a PhfSet<K> {
249    type Item = &'a K;
250    type IntoIter = Iter<'a, K>;
251
252    fn into_iter(self) -> Iter<'a, K> {
253        self.iter()
254    }
255}
256
257impl<K: Eq + Hash> PartialEq for PhfSet<K> {
258    fn eq(&self, other: &Self) -> bool {
259        if self.len() != other.len() {
260            return false;
261        }
262
263        self.iter().all(|k| other.contains(k))
264    }
265}
266
267impl<K: Eq + Hash> Eq for PhfSet<K> {}
268
269#[derive(Clone)]
270/// An iterator over the elements of a `PhfSet`.
271pub struct Iter<'a, K: 'a> {
272    iter: crate::raw_map::Iter<'a, K>,
273}
274
275impl<'a, K> Iterator for Iter<'a, K> {
276    type Item = &'a K;
277
278    fn next(&mut self) -> Option<Self::Item> {
279        self.iter.next()
280    }
281
282    fn size_hint(&self) -> (usize, Option<usize>) {
283        self.iter.size_hint()
284    }
285}
286
287impl<'a, K> ExactSizeIterator for Iter<'a, K> {}
288
289impl<'a, K> core::iter::FusedIterator for Iter<'a, K> {}
290
291#[derive(Clone)]
292/// A lazy iterator producing elements from the difference of two `PhfSets`s.
293pub struct Difference<'a, K: 'static> {
294    iter: Iter<'a, K>,
295    other: &'a PhfSet<K>,
296}
297
298impl<'a, K> Iterator for Difference<'a, K>
299where
300    K: Eq + Hash,
301{
302    type Item = &'a K;
303
304    fn next(&mut self) -> Option<Self::Item> {
305        self.iter.by_ref().find(|&k| !self.other.contains(k))
306    }
307
308    fn size_hint(&self) -> (usize, Option<usize>) {
309        let self_size = self.iter.size_hint().0;
310        let other_size = self.other.len();
311        let min_size = self_size.saturating_sub(other_size);
312
313        (min_size, Some(self_size))
314    }
315}
316
317impl<'a, K> core::iter::FusedIterator for Difference<'a, K> where K: Eq + Hash {}
318
319#[derive(Clone)]
320/// A lazy iterator producing elements from the intersection of two `PhfSet`s.
321pub struct Intersection<'a, K: 'static> {
322    iter: Iter<'a, K>,
323    other: &'a PhfSet<K>,
324}
325
326impl<'a, K> Iterator for Intersection<'a, K>
327where
328    K: Eq + Hash,
329{
330    type Item = &'a K;
331
332    fn next(&mut self) -> Option<Self::Item> {
333        self.iter.by_ref().find(|&k| self.other.contains(k))
334    }
335
336    fn size_hint(&self) -> (usize, Option<usize>) {
337        let self_size = self.iter.size_hint().0;
338        let other_size = self.other.len();
339        let max_size = usize::min(self_size, other_size);
340
341        (0, Some(max_size))
342    }
343}
344
345impl<'a, K> core::iter::FusedIterator for Intersection<'a, K> where K: Eq + Hash {}
346
347#[derive(Clone)]
348/// A lazy iterator producing elements from the symmetric difference of two `PhfSet`s.
349pub struct SymmetricDifference<'a, K: 'static> {
350    iter: core::iter::Chain<Difference<'a, K>, Difference<'a, K>>,
351}
352
353impl<'a, K> Iterator for SymmetricDifference<'a, K>
354where
355    K: Eq + Hash,
356{
357    type Item = &'a K;
358
359    fn next(&mut self) -> Option<Self::Item> {
360        self.iter.next()
361    }
362
363    fn size_hint(&self) -> (usize, Option<usize>) {
364        self.iter.size_hint()
365    }
366}
367
368impl<'a, K> core::iter::FusedIterator for SymmetricDifference<'a, K> where K: Eq + Hash {}
369
370#[derive(Clone)]
371/// A lazy iterator producing elements from the union of two `PhfSet`s.
372pub struct Union<'a, K: 'static> {
373    iter: core::iter::Chain<Iter<'a, K>, Difference<'a, K>>,
374}
375
376impl<'a, K> Iterator for Union<'a, K>
377where
378    K: Eq + Hash,
379{
380    type Item = &'a K;
381
382    fn next(&mut self) -> Option<Self::Item> {
383        self.iter.next()
384    }
385
386    fn size_hint(&self) -> (usize, Option<usize>) {
387        self.iter.size_hint()
388    }
389}
390
391impl<'a, K> core::iter::FusedIterator for Union<'a, K> where K: Eq + Hash {}
392
393#[cfg(test)]
394mod tests {
395    use crate::examples::EMPTY_SET;
396
397    use super::*;
398
399    #[test]
400    fn test_empty() {
401        assert_eq!(EMPTY_SET.get(&17), None);
402        assert!(!EMPTY_SET.contains(&620));
403        assert!(EMPTY_SET.iter().next().is_none())
404    }
405
406    #[test]
407    fn test_sync() {
408        fn assert_sync<T: Sync>() {}
409        assert_sync::<PhfSet<u64>>();
410    }
411}