heapless/
indexset.rs

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