heapless/
index_set.rs

1//! A fixed-capacity hash set where the iteration order is independent of the hash values.
2use core::{
3    borrow::Borrow,
4    fmt,
5    hash::{BuildHasher, Hash},
6};
7
8use hash32::{BuildHasherDefault, FnvHasher};
9
10use crate::index_map::{self, IndexMap};
11
12/// An [`IndexSet`] using the default FNV hasher.
13///
14/// A list of all Methods and Traits available for `FnvIndexSet` can be found in
15/// the [`IndexSet`] documentation.
16///
17/// # Examples
18/// ```
19/// use heapless::index_set::FnvIndexSet;
20///
21/// // A hash set with a capacity of 16 elements allocated on the stack
22/// let mut books = FnvIndexSet::<_, 16>::new();
23///
24/// // Add some books.
25/// books.insert("A Dance With Dragons").unwrap();
26/// books.insert("To Kill a Mockingbird").unwrap();
27/// books.insert("The Odyssey").unwrap();
28/// books.insert("The Great Gatsby").unwrap();
29///
30/// // Check for a specific one.
31/// if !books.contains("The Winds of Winter") {
32///     println!(
33///         "We have {} books, but The Winds of Winter ain't one.",
34///         books.len()
35///     );
36/// }
37///
38/// // Remove a book.
39/// books.remove("The Odyssey");
40///
41/// // Iterate over everything.
42/// for book in &books {
43///     println!("{}", book);
44/// }
45/// ```
46pub type FnvIndexSet<T, const N: usize> = IndexSet<T, BuildHasherDefault<FnvHasher>, N>;
47
48/// Fixed capacity [`IndexSet`](https://docs.rs/indexmap/2/indexmap/set/struct.IndexSet.html).
49///
50/// Note that you cannot use `IndexSet` directly, since it is generic around the hashing algorithm
51/// in use. Pick a concrete instantiation like [`FnvIndexSet`] instead
52/// or create your own.
53///
54/// Note that the capacity of the `IndexSet` must be a power of 2.
55///
56/// # Examples
57/// Since `IndexSet` cannot be used directly, we're using its `FnvIndexSet` instantiation
58/// for this example.
59///
60/// ```
61/// use heapless::index_set::FnvIndexSet;
62///
63/// // A hash set with a capacity of 16 elements allocated on the stack
64/// let mut books = FnvIndexSet::<_, 16>::new();
65///
66/// // Add some books.
67/// books.insert("A Dance With Dragons").unwrap();
68/// books.insert("To Kill a Mockingbird").unwrap();
69/// books.insert("The Odyssey").unwrap();
70/// books.insert("The Great Gatsby").unwrap();
71///
72/// // Check for a specific one.
73/// if !books.contains("The Winds of Winter") {
74///     println!(
75///         "We have {} books, but The Winds of Winter ain't one.",
76///         books.len()
77///     );
78/// }
79///
80/// // Remove a book.
81/// books.remove("The Odyssey");
82///
83/// // Iterate over everything.
84/// for book in &books {
85///     println!("{}", book);
86/// }
87/// ```
88pub struct IndexSet<T, S, const N: usize> {
89    map: IndexMap<T, (), S, N>,
90}
91
92impl<T, S, const N: usize> IndexSet<T, BuildHasherDefault<S>, N> {
93    /// Creates an empty `IndexSet`
94    pub const fn new() -> Self {
95        Self {
96            map: IndexMap::new(),
97        }
98    }
99}
100
101impl<T, S, const N: usize> IndexSet<T, S, N> {
102    /// Returns the number of elements the set can hold
103    ///
104    /// # Examples
105    ///
106    /// ```
107    /// use heapless::index_set::FnvIndexSet;
108    ///
109    /// let set = FnvIndexSet::<i32, 16>::new();
110    /// assert_eq!(set.capacity(), 16);
111    /// ```
112    pub fn capacity(&self) -> usize {
113        self.map.capacity()
114    }
115
116    /// Return an iterator over the values of the set, in insertion order
117    ///
118    /// # Examples
119    ///
120    /// ```
121    /// use heapless::index_set::FnvIndexSet;
122    ///
123    /// let mut set = FnvIndexSet::<_, 16>::new();
124    /// set.insert("a").unwrap();
125    /// set.insert("b").unwrap();
126    ///
127    /// // Will print in insertion order: a, b
128    /// for x in set.iter() {
129    ///     println!("{}", x);
130    /// }
131    /// ```
132    pub fn iter(&self) -> Iter<'_, T> {
133        Iter {
134            iter: self.map.iter(),
135        }
136    }
137
138    /// Get the first value
139    ///
140    /// Computes in *O*(1) time
141    pub fn first(&self) -> Option<&T> {
142        self.map.first().map(|(k, _v)| k)
143    }
144
145    /// Get the last value
146    ///
147    /// Computes in *O*(1) time
148    pub fn last(&self) -> Option<&T> {
149        self.map.last().map(|(k, _v)| k)
150    }
151
152    /// Returns the number of elements in the set.
153    ///
154    /// # Examples
155    ///
156    /// ```
157    /// use heapless::index_set::FnvIndexSet;
158    ///
159    /// let mut v: FnvIndexSet<_, 16> = FnvIndexSet::new();
160    /// assert_eq!(v.len(), 0);
161    /// v.insert(1).unwrap();
162    /// assert_eq!(v.len(), 1);
163    /// ```
164    pub fn len(&self) -> usize {
165        self.map.len()
166    }
167
168    /// Returns `true` if the set contains no elements.
169    ///
170    /// # Examples
171    ///
172    /// ```
173    /// use heapless::index_set::FnvIndexSet;
174    ///
175    /// let mut v: FnvIndexSet<_, 16> = FnvIndexSet::new();
176    /// assert!(v.is_empty());
177    /// v.insert(1).unwrap();
178    /// assert!(!v.is_empty());
179    /// ```
180    pub fn is_empty(&self) -> bool {
181        self.map.is_empty()
182    }
183
184    /// Returns `true` if the set is full.
185    ///
186    /// # Examples
187    ///
188    /// ```
189    /// use heapless::index_set::FnvIndexSet;
190    ///
191    /// let mut v: FnvIndexSet<_, 4> = FnvIndexSet::new();
192    /// assert!(!v.is_full());
193    /// v.insert(1).unwrap();
194    /// v.insert(2).unwrap();
195    /// v.insert(3).unwrap();
196    /// v.insert(4).unwrap();
197    /// assert!(v.is_full());
198    /// ```
199    pub fn is_full(&self) -> bool {
200        self.map.is_full()
201    }
202
203    /// Clears the set, removing all values.
204    ///
205    /// # Examples
206    ///
207    /// ```
208    /// use heapless::index_set::FnvIndexSet;
209    ///
210    /// let mut v: FnvIndexSet<_, 16> = FnvIndexSet::new();
211    /// v.insert(1).unwrap();
212    /// v.clear();
213    /// assert!(v.is_empty());
214    /// ```
215    pub fn clear(&mut self) {
216        self.map.clear();
217    }
218}
219
220impl<T, S, const N: usize> IndexSet<T, S, N>
221where
222    T: Eq + Hash,
223    S: BuildHasher,
224{
225    /// Visits the values representing the difference, i.e. the values that are in `self` but not in
226    /// `other`.
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// use heapless::index_set::FnvIndexSet;
232    ///
233    /// let mut a: FnvIndexSet<_, 16> = [1, 2, 3].iter().cloned().collect();
234    /// let mut b: FnvIndexSet<_, 16> = [4, 2, 3, 4].iter().cloned().collect();
235    ///
236    /// // Can be seen as `a - b`.
237    /// for x in a.difference(&b) {
238    ///     println!("{}", x); // Print 1
239    /// }
240    ///
241    /// let diff: FnvIndexSet<_, 16> = a.difference(&b).collect();
242    /// assert_eq!(diff, [1].iter().collect::<FnvIndexSet<_, 16>>());
243    ///
244    /// // Note that difference is not symmetric,
245    /// // and `b - a` means something else:
246    /// let diff: FnvIndexSet<_, 16> = b.difference(&a).collect();
247    /// assert_eq!(diff, [4].iter().collect::<FnvIndexSet<_, 16>>());
248    /// ```
249    pub fn difference<'a, S2, const N2: usize>(
250        &'a self,
251        other: &'a IndexSet<T, S2, N2>,
252    ) -> Difference<'a, T, S2, N2>
253    where
254        S2: BuildHasher,
255    {
256        Difference {
257            iter: self.iter(),
258            other,
259        }
260    }
261
262    /// Visits the values representing the symmetric difference, i.e. the values that are in `self`
263    /// or in `other` but not in both.
264    ///
265    /// # Examples
266    ///
267    /// ```
268    /// use heapless::index_set::FnvIndexSet;
269    ///
270    /// let mut a: FnvIndexSet<_, 16> = [1, 2, 3].iter().cloned().collect();
271    /// let mut b: FnvIndexSet<_, 16> = [4, 2, 3, 4].iter().cloned().collect();
272    ///
273    /// // Print 1, 4 in that order.
274    /// for x in a.symmetric_difference(&b) {
275    ///     println!("{}", x);
276    /// }
277    ///
278    /// let diff1: FnvIndexSet<_, 16> = a.symmetric_difference(&b).collect();
279    /// let diff2: FnvIndexSet<_, 16> = b.symmetric_difference(&a).collect();
280    ///
281    /// assert_eq!(diff1, diff2);
282    /// assert_eq!(diff1, [1, 4].iter().collect::<FnvIndexSet<_, 16>>());
283    /// ```
284    pub fn symmetric_difference<'a, S2, const N2: usize>(
285        &'a self,
286        other: &'a IndexSet<T, S2, N2>,
287    ) -> impl Iterator<Item = &'a T>
288    where
289        S2: BuildHasher,
290    {
291        self.difference(other).chain(other.difference(self))
292    }
293
294    /// Visits the values representing the intersection, i.e. the values that are both in `self` and
295    /// `other`.
296    ///
297    /// # Examples
298    ///
299    /// ```
300    /// use heapless::index_set::FnvIndexSet;
301    ///
302    /// let mut a: FnvIndexSet<_, 16> = [1, 2, 3].iter().cloned().collect();
303    /// let mut b: FnvIndexSet<_, 16> = [4, 2, 3, 4].iter().cloned().collect();
304    ///
305    /// // Print 2, 3 in that order.
306    /// for x in a.intersection(&b) {
307    ///     println!("{}", x);
308    /// }
309    ///
310    /// let intersection: FnvIndexSet<_, 16> = a.intersection(&b).collect();
311    /// assert_eq!(intersection, [2, 3].iter().collect::<FnvIndexSet<_, 16>>());
312    /// ```
313    pub fn intersection<'a, S2, const N2: usize>(
314        &'a self,
315        other: &'a IndexSet<T, S2, N2>,
316    ) -> Intersection<'a, T, S2, N2>
317    where
318        S2: BuildHasher,
319    {
320        Intersection {
321            iter: self.iter(),
322            other,
323        }
324    }
325
326    /// Visits the values representing the union, i.e. all the values in `self` or `other`, without
327    /// duplicates.
328    ///
329    /// # Examples
330    ///
331    /// ```
332    /// use heapless::index_set::FnvIndexSet;
333    ///
334    /// let mut a: FnvIndexSet<_, 16> = [1, 2, 3].iter().cloned().collect();
335    /// let mut b: FnvIndexSet<_, 16> = [4, 2, 3, 4].iter().cloned().collect();
336    ///
337    /// // Print 1, 2, 3, 4 in that order.
338    /// for x in a.union(&b) {
339    ///     println!("{}", x);
340    /// }
341    ///
342    /// let union: FnvIndexSet<_, 16> = a.union(&b).collect();
343    /// assert_eq!(union, [1, 2, 3, 4].iter().collect::<FnvIndexSet<_, 16>>());
344    /// ```
345    pub fn union<'a, S2, const N2: usize>(
346        &'a self,
347        other: &'a IndexSet<T, S2, N2>,
348    ) -> impl Iterator<Item = &'a T>
349    where
350        S2: BuildHasher,
351    {
352        self.iter().chain(other.difference(self))
353    }
354
355    /// Returns `true` if the set contains a value.
356    ///
357    /// The value may be any borrowed form of the set's value type, but `Hash` and `Eq` on the
358    /// borrowed form must match those for the value type.
359    ///
360    /// # Examples
361    ///
362    /// ```
363    /// use heapless::index_set::FnvIndexSet;
364    ///
365    /// let set: FnvIndexSet<_, 16> = [1, 2, 3].iter().cloned().collect();
366    /// assert_eq!(set.contains(&1), true);
367    /// assert_eq!(set.contains(&4), false);
368    /// ```
369    pub fn contains<Q>(&self, value: &Q) -> bool
370    where
371        T: Borrow<Q>,
372        Q: ?Sized + Eq + Hash,
373    {
374        self.map.contains_key(value)
375    }
376
377    /// Returns `true` if `self` has no elements in common with `other`. This is equivalent to
378    /// checking for an empty intersection.
379    ///
380    /// # Examples
381    ///
382    /// ```
383    /// use heapless::index_set::FnvIndexSet;
384    ///
385    /// let a: FnvIndexSet<_, 16> = [1, 2, 3].iter().cloned().collect();
386    /// let mut b = FnvIndexSet::<_, 16>::new();
387    ///
388    /// assert_eq!(a.is_disjoint(&b), true);
389    /// b.insert(4).unwrap();
390    /// assert_eq!(a.is_disjoint(&b), true);
391    /// b.insert(1).unwrap();
392    /// assert_eq!(a.is_disjoint(&b), false);
393    /// ```
394    pub fn is_disjoint<S2, const N2: usize>(&self, other: &IndexSet<T, S2, N2>) -> bool
395    where
396        S2: BuildHasher,
397    {
398        self.iter().all(|v| !other.contains(v))
399    }
400
401    /// Returns `true` if the set is a subset of another, i.e. `other` contains at least all the
402    /// values in `self`.
403    ///
404    /// # Examples
405    ///
406    /// ```
407    /// use heapless::index_set::FnvIndexSet;
408    ///
409    /// let sup: FnvIndexSet<_, 16> = [1, 2, 3].iter().cloned().collect();
410    /// let mut set = FnvIndexSet::<_, 16>::new();
411    ///
412    /// assert_eq!(set.is_subset(&sup), true);
413    /// set.insert(2).unwrap();
414    /// assert_eq!(set.is_subset(&sup), true);
415    /// set.insert(4).unwrap();
416    /// assert_eq!(set.is_subset(&sup), false);
417    /// ```
418    pub fn is_subset<S2, const N2: usize>(&self, other: &IndexSet<T, S2, N2>) -> bool
419    where
420        S2: BuildHasher,
421    {
422        self.iter().all(|v| other.contains(v))
423    }
424
425    // Returns `true` if the set is a superset of another, i.e. `self` contains at least all the
426    // values in `other`.
427    ///
428    /// # Examples
429    ///
430    /// ```
431    /// use heapless::index_set::FnvIndexSet;
432    ///
433    /// let sub: FnvIndexSet<_, 16> = [1, 2].iter().cloned().collect();
434    /// let mut set = FnvIndexSet::<_, 16>::new();
435    ///
436    /// assert_eq!(set.is_superset(&sub), false);
437    ///
438    /// set.insert(0).unwrap();
439    /// set.insert(1).unwrap();
440    /// assert_eq!(set.is_superset(&sub), false);
441    ///
442    /// set.insert(2).unwrap();
443    /// assert_eq!(set.is_superset(&sub), true);
444    /// ```
445    pub fn is_superset<S2, const N2: usize>(&self, other: &IndexSet<T, S2, N2>) -> bool
446    where
447        S2: BuildHasher,
448    {
449        other.is_subset(self)
450    }
451
452    /// Adds a value to the set.
453    ///
454    /// If the set did not have this value present, `true` is returned.
455    ///
456    /// If the set did have this value present, `false` is returned.
457    ///
458    /// # Examples
459    ///
460    /// ```
461    /// use heapless::index_set::FnvIndexSet;
462    ///
463    /// let mut set = FnvIndexSet::<_, 16>::new();
464    ///
465    /// assert_eq!(set.insert(2).unwrap(), true);
466    /// assert_eq!(set.insert(2).unwrap(), false);
467    /// assert_eq!(set.len(), 1);
468    /// ```
469    pub fn insert(&mut self, value: T) -> Result<bool, T> {
470        self.map
471            .insert(value, ())
472            .map(|old| old.is_none())
473            .map_err(|(k, _)| k)
474    }
475
476    /// Removes a value from the set. Returns `true` if the value was present in the set.
477    ///
478    /// The value may be any borrowed form of the set's value type, but `Hash` and `Eq` on the
479    /// borrowed form must match those for the value type.
480    ///
481    /// # Examples
482    ///
483    /// ```
484    /// use heapless::index_set::FnvIndexSet;
485    ///
486    /// let mut set = FnvIndexSet::<_, 16>::new();
487    ///
488    /// set.insert(2).unwrap();
489    /// assert_eq!(set.remove(&2), true);
490    /// assert_eq!(set.remove(&2), false);
491    /// ```
492    pub fn remove<Q>(&mut self, value: &Q) -> bool
493    where
494        T: Borrow<Q>,
495        Q: ?Sized + Eq + Hash,
496    {
497        self.map.remove(value).is_some()
498    }
499
500    /// Retains only the elements specified by the predicate.
501    ///
502    /// In other words, remove all elements `e` for which `f(&e)` returns `false`.
503    pub fn retain<F>(&mut self, mut f: F)
504    where
505        F: FnMut(&T) -> bool,
506    {
507        self.map.retain(move |k, _| f(k));
508    }
509}
510
511impl<T, S, const N: usize> Clone for IndexSet<T, S, N>
512where
513    T: Clone,
514    S: Clone,
515{
516    fn clone(&self) -> Self {
517        Self {
518            map: self.map.clone(),
519        }
520    }
521}
522
523impl<T, S, const N: usize> fmt::Debug for IndexSet<T, S, N>
524where
525    T: fmt::Debug,
526{
527    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528        f.debug_set().entries(self.iter()).finish()
529    }
530}
531
532impl<T, S, const N: usize> Default for IndexSet<T, S, N>
533where
534    S: Default,
535{
536    fn default() -> Self {
537        Self {
538            map: <_>::default(),
539        }
540    }
541}
542
543impl<T, S1, S2, const N1: usize, const N2: usize> PartialEq<IndexSet<T, S2, N2>>
544    for IndexSet<T, S1, N1>
545where
546    T: Eq + Hash,
547    S1: BuildHasher,
548    S2: BuildHasher,
549{
550    fn eq(&self, other: &IndexSet<T, S2, N2>) -> bool {
551        self.len() == other.len() && self.is_subset(other)
552    }
553}
554
555impl<T, S, const N: usize> Extend<T> for IndexSet<T, S, N>
556where
557    T: Eq + Hash,
558    S: BuildHasher,
559{
560    fn extend<I>(&mut self, iterable: I)
561    where
562        I: IntoIterator<Item = T>,
563    {
564        self.map.extend(iterable.into_iter().map(|k| (k, ())));
565    }
566}
567
568impl<'a, T, S, const N: usize> Extend<&'a T> for IndexSet<T, S, N>
569where
570    T: 'a + Eq + Hash + Copy,
571    S: BuildHasher,
572{
573    fn extend<I>(&mut self, iterable: I)
574    where
575        I: IntoIterator<Item = &'a T>,
576    {
577        self.extend(iterable.into_iter().cloned());
578    }
579}
580
581impl<T, S, const N: usize> FromIterator<T> for IndexSet<T, S, N>
582where
583    T: Eq + Hash,
584    S: BuildHasher + Default,
585{
586    fn from_iter<I>(iter: I) -> Self
587    where
588        I: IntoIterator<Item = T>,
589    {
590        let mut set = Self::default();
591        set.extend(iter);
592        set
593    }
594}
595
596impl<'a, T, S, const N: usize> IntoIterator for &'a IndexSet<T, S, N>
597where
598    T: Eq + Hash,
599    S: BuildHasher,
600{
601    type Item = &'a T;
602    type IntoIter = Iter<'a, T>;
603
604    fn into_iter(self) -> Self::IntoIter {
605        self.iter()
606    }
607}
608
609/// An iterator over the items of a [`IndexSet`].
610///
611/// This `struct` is created by the [`iter`](IndexSet::iter) method on [`IndexSet`]. See its
612/// documentation for more.
613pub struct Iter<'a, T> {
614    iter: index_map::Iter<'a, T, ()>,
615}
616
617impl<'a, T> Iterator for Iter<'a, T> {
618    type Item = &'a T;
619
620    fn next(&mut self) -> Option<Self::Item> {
621        self.iter.next().map(|(k, _)| k)
622    }
623}
624
625impl<T> Clone for Iter<'_, T> {
626    fn clone(&self) -> Self {
627        Self {
628            iter: self.iter.clone(),
629        }
630    }
631}
632
633/// An iterator over the difference of two `IndexSet`s.
634///
635/// This is created by the [`IndexSet::difference`] method.
636pub struct Difference<'a, T, S, const N: usize>
637where
638    S: BuildHasher,
639    T: Eq + Hash,
640{
641    iter: Iter<'a, T>,
642    other: &'a IndexSet<T, S, N>,
643}
644
645impl<'a, T, S, const N: usize> Iterator for Difference<'a, T, S, N>
646where
647    S: BuildHasher,
648    T: Eq + Hash,
649{
650    type Item = &'a T;
651
652    fn next(&mut self) -> Option<Self::Item> {
653        loop {
654            let elt = self.iter.next()?;
655            if !self.other.contains(elt) {
656                return Some(elt);
657            }
658        }
659    }
660}
661
662/// An iterator over the intersection of two `IndexSet`s.
663///
664/// This is created by the [`IndexSet::intersection`] method.
665pub struct Intersection<'a, T, S, const N: usize>
666where
667    S: BuildHasher,
668    T: Eq + Hash,
669{
670    iter: Iter<'a, T>,
671    other: &'a IndexSet<T, S, N>,
672}
673
674impl<'a, T, S, const N: usize> Iterator for Intersection<'a, T, S, N>
675where
676    S: BuildHasher,
677    T: Eq + Hash,
678{
679    type Item = &'a T;
680
681    fn next(&mut self) -> Option<Self::Item> {
682        loop {
683            let elt = self.iter.next()?;
684            if self.other.contains(elt) {
685                return Some(elt);
686            }
687        }
688    }
689}
690
691#[cfg(test)]
692mod tests {
693    use static_assertions::assert_not_impl_any;
694
695    use super::{BuildHasherDefault, IndexSet};
696
697    // Ensure a `IndexSet` containing `!Send` values stays `!Send` itself.
698    assert_not_impl_any!(IndexSet<*const (), BuildHasherDefault<()>, 4>: Send);
699}