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}