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}