use core::borrow::Borrow; use core::fmt; use core::iter::FromIterator; use generic_array::typenum::PowerOfTwo; use generic_array::ArrayLength; use hash32::{BuildHasher, BuildHasherDefault, FnvHasher, Hash, Hasher}; use indexmap::{self, Bucket, IndexMap, Pos}; /// An `IndexSet` using the default FNV hasher pub type FnvIndexSet = IndexSet>; /// Fixed capacity [`IndexSet`](https://docs.rs/indexmap/1/indexmap/set/struct.IndexSet.html) /// /// Note that the capacity of the `IndexSet` must be a power of 2. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// // A hash set with a capacity of 16 elements /// let mut books = FnvIndexSet::<_, U16>::new(); /// /// // Add some books. /// books.insert("A Dance With Dragons").unwrap(); /// books.insert("To Kill a Mockingbird").unwrap(); /// books.insert("The Odyssey").unwrap(); /// books.insert("The Great Gatsby").unwrap(); /// /// // Check for a specific one. /// if !books.contains("The Winds of Winter") { /// println!("We have {} books, but The Winds of Winter ain't one.", /// books.len()); /// } /// /// // Remove a book. /// books.remove("The Odyssey"); /// /// // Iterate over everything. /// for book in &books { /// println!("{}", book); /// } /// ``` pub struct IndexSet where T: Eq + Hash, N: ArrayLength> + ArrayLength>, { map: IndexMap, } impl IndexSet> where T: Eq + Hash, S: Default + Hasher, N: ArrayLength> + ArrayLength> + PowerOfTwo, { /// Creates an empty `IndexSet` pub fn new() -> Self { IndexSet { map: IndexMap::new(), } } } impl IndexSet where T: Eq + Hash, S: BuildHasher, N: ArrayLength> + ArrayLength>, { /// Returns the number of elements the set can hold /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let set = FnvIndexSet::::new(); /// assert_eq!(set.capacity(), 16); /// ``` pub fn capacity(&self) -> usize { self.map.capacity() } /// Return an iterator over the values of the set, in their order /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut set = FnvIndexSet::<_, U16>::new(); /// set.insert("a").unwrap(); /// set.insert("b").unwrap(); /// /// // Will print in an arbitrary order. /// for x in set.iter() { /// println!("{}", x); /// } /// ``` pub fn iter(&self) -> Iter { Iter { iter: self.map.iter(), } } /// Visits the values representing the difference, i.e. the values that are in `self` but not in /// `other`. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut a: FnvIndexSet<_, U16> = [1, 2, 3].iter().cloned().collect(); /// let mut b: FnvIndexSet<_, U16> = [4, 2, 3, 4].iter().cloned().collect(); /// /// // Can be seen as `a - b`. /// for x in a.difference(&b) { /// println!("{}", x); // Print 1 /// } /// /// let diff: FnvIndexSet<_, U16> = a.difference(&b).collect(); /// assert_eq!(diff, [1].iter().collect::>()); /// /// // Note that difference is not symmetric, /// // and `b - a` means something else: /// let diff: FnvIndexSet<_, U16> = b.difference(&a).collect(); /// assert_eq!(diff, [4].iter().collect::>()); /// ``` pub fn difference<'a, N2, S2>( &'a self, other: &'a IndexSet, ) -> Difference<'a, T, N2, S2> where N2: ArrayLength> + ArrayLength>, S2: BuildHasher, { Difference { iter: self.iter(), other, } } /// Visits the values representing the symmetric difference, i.e. the values that are in `self` /// or in `other` but not in both. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut a: FnvIndexSet<_, U16> = [1, 2, 3].iter().cloned().collect(); /// let mut b: FnvIndexSet<_, U16> = [4, 2, 3, 4].iter().cloned().collect(); /// /// // Print 1, 4 in that order order. /// for x in a.symmetric_difference(&b) { /// println!("{}", x); /// } /// /// let diff1: FnvIndexSet<_, U16> = a.symmetric_difference(&b).collect(); /// let diff2: FnvIndexSet<_, U16> = b.symmetric_difference(&a).collect(); /// /// assert_eq!(diff1, diff2); /// assert_eq!(diff1, [1, 4].iter().collect::>()); /// ``` pub fn symmetric_difference<'a, N2, S2>( &'a self, other: &'a IndexSet, ) -> impl Iterator where N2: ArrayLength> + ArrayLength>, S2: BuildHasher, { self.difference(other).chain(other.difference(self)) } /// Visits the values representing the intersection, i.e. the values that are both in `self` and /// `other`. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut a: FnvIndexSet<_, U16> = [1, 2, 3].iter().cloned().collect(); /// let mut b: FnvIndexSet<_, U16> = [4, 2, 3, 4].iter().cloned().collect(); /// /// // Print 2, 3 in that order. /// for x in a.intersection(&b) { /// println!("{}", x); /// } /// /// let intersection: FnvIndexSet<_, U16> = a.intersection(&b).collect(); /// assert_eq!(intersection, [2, 3].iter().collect::>()); /// ``` pub fn intersection<'a, N2, S2>( &'a self, other: &'a IndexSet, ) -> Intersection<'a, T, N2, S2> where N2: ArrayLength> + ArrayLength>, S2: BuildHasher, { Intersection { iter: self.iter(), other, } } /// Visits the values representing the union, i.e. all the values in `self` or `other`, without /// duplicates. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut a: FnvIndexSet<_, U16> = [1, 2, 3].iter().cloned().collect(); /// let mut b: FnvIndexSet<_, U16> = [4, 2, 3, 4].iter().cloned().collect(); /// /// // Print 1, 2, 3, 4 in that order. /// for x in a.union(&b) { /// println!("{}", x); /// } /// /// let union: FnvIndexSet<_, U16> = a.union(&b).collect(); /// assert_eq!(union, [1, 2, 3, 4].iter().collect::>()); /// ``` pub fn union<'a, N2, S2>( &'a self, other: &'a IndexSet, ) -> impl Iterator where N2: ArrayLength> + ArrayLength>, S2: BuildHasher, { self.iter().chain(other.difference(self)) } /// Returns the number of elements in the set. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut v: FnvIndexSet<_, U16> = FnvIndexSet::new(); /// assert_eq!(v.len(), 0); /// v.insert(1).unwrap(); /// assert_eq!(v.len(), 1); /// ``` pub fn len(&self) -> usize { self.map.len() } /// Returns `true` if the set contains no elements. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut v: FnvIndexSet<_, U16> = FnvIndexSet::new(); /// assert!(v.is_empty()); /// v.insert(1).unwrap(); /// assert!(!v.is_empty()); /// ``` pub fn is_empty(&self) -> bool { self.map.is_empty() } /// Clears the set, removing all values. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut v: FnvIndexSet<_, U16> = FnvIndexSet::new(); /// v.insert(1).unwrap(); /// v.clear(); /// assert!(v.is_empty()); /// ``` pub fn clear(&mut self) { self.map.clear() } /// Returns `true` if the set contains a value. /// /// The value may be any borrowed form of the set's value type, but `Hash` and `Eq` on the /// borrowed form must match those for the value type. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let set: FnvIndexSet<_, U16> = [1, 2, 3].iter().cloned().collect(); /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` pub fn contains(&self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Eq + Hash, { self.map.contains_key(value) } /// Returns `true` if `self` has no elements in common with `other`. This is equivalent to /// checking for an empty intersection. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let a: FnvIndexSet<_, U16> = [1, 2, 3].iter().cloned().collect(); /// let mut b = FnvIndexSet::<_, U16>::new(); /// /// assert_eq!(a.is_disjoint(&b), true); /// b.insert(4).unwrap(); /// assert_eq!(a.is_disjoint(&b), true); /// b.insert(1).unwrap(); /// assert_eq!(a.is_disjoint(&b), false); /// ``` pub fn is_disjoint(&self, other: &IndexSet) -> bool where N2: ArrayLength> + ArrayLength>, S2: BuildHasher, { self.iter().all(|v| !other.contains(v)) } /// Returns `true` if the set is a subset of another, i.e. `other` contains at least all the /// values in `self`. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let sup: FnvIndexSet<_, U16> = [1, 2, 3].iter().cloned().collect(); /// let mut set = FnvIndexSet::<_, U16>::new(); /// /// assert_eq!(set.is_subset(&sup), true); /// set.insert(2).unwrap(); /// assert_eq!(set.is_subset(&sup), true); /// set.insert(4).unwrap(); /// assert_eq!(set.is_subset(&sup), false); /// ``` pub fn is_subset(&self, other: &IndexSet) -> bool where N2: ArrayLength> + ArrayLength>, S2: BuildHasher, { self.iter().all(|v| other.contains(v)) } // Returns `true` if the set is a superset of another, i.e. `self` contains at least all the // values in `other`. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let sub: FnvIndexSet<_, U16> = [1, 2].iter().cloned().collect(); /// let mut set = FnvIndexSet::<_, U16>::new(); /// /// assert_eq!(set.is_superset(&sub), false); /// /// set.insert(0).unwrap(); /// set.insert(1).unwrap(); /// assert_eq!(set.is_superset(&sub), false); /// /// set.insert(2).unwrap(); /// assert_eq!(set.is_superset(&sub), true); /// ``` pub fn is_superset(&self, other: &IndexSet) -> bool where N2: ArrayLength> + ArrayLength>, S2: BuildHasher, { other.is_subset(self) } /// Adds a value to the set. /// /// If the set did not have this value present, `true` is returned. /// /// If the set did have this value present, `false` is returned. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut set = FnvIndexSet::<_, U16>::new(); /// /// assert_eq!(set.insert(2).unwrap(), true); /// assert_eq!(set.insert(2).unwrap(), false); /// assert_eq!(set.len(), 1); /// ``` pub fn insert(&mut self, value: T) -> Result { self.map .insert(value, ()) .map(|old| old.is_none()) .map_err(|(k, _)| k) } /// Removes a value from the set. Returns `true` if the value was present in the set. /// /// The value may be any borrowed form of the set's value type, but `Hash` and `Eq` on the /// borrowed form must match those for the value type. /// /// # Examples /// /// ``` /// use heapless::FnvIndexSet; /// use heapless::consts::*; /// /// let mut set = FnvIndexSet::<_, U16>::new(); /// /// set.insert(2).unwrap(); /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, Q: ?Sized + Eq + Hash, { self.map.remove(value).is_some() } } impl fmt::Debug for IndexSet where T: Eq + Hash + fmt::Debug, S: BuildHasher, N: ArrayLength> + ArrayLength>, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_set().entries(self.iter()).finish() } } impl Default for IndexSet where T: Eq + Hash, S: BuildHasher + Default, N: ArrayLength> + ArrayLength>, { fn default() -> Self { IndexSet { map: <_>::default(), } } } impl PartialEq> for IndexSet where T: Eq + Hash, S1: BuildHasher, S2: BuildHasher, N1: ArrayLength> + ArrayLength>, N2: ArrayLength> + ArrayLength>, { fn eq(&self, other: &IndexSet) -> bool { self.len() == other.len() && self.is_subset(other) } } impl Extend for IndexSet where T: Eq + Hash, S: BuildHasher, N: ArrayLength> + ArrayLength>, { fn extend(&mut self, iterable: I) where I: IntoIterator, { self.map.extend(iterable.into_iter().map(|k| (k, ()))) } } impl<'a, T, N, S> Extend<&'a T> for IndexSet where T: 'a + Eq + Hash + Copy, S: BuildHasher, N: ArrayLength> + ArrayLength>, { fn extend(&mut self, iterable: I) where I: IntoIterator, { self.extend(iterable.into_iter().cloned()) } } impl FromIterator for IndexSet where T: Eq + Hash, S: BuildHasher + Default, N: ArrayLength> + ArrayLength>, { fn from_iter(iter: I) -> Self where I: IntoIterator, { let mut set = IndexSet::default(); set.extend(iter); set } } impl<'a, T, N, S> IntoIterator for &'a IndexSet where T: Eq + Hash, S: BuildHasher, N: ArrayLength> + ArrayLength>, { type Item = &'a T; type IntoIter = Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } } pub struct Iter<'a, T> where T: 'a, { iter: indexmap::Iter<'a, T, ()>, } impl<'a, T> Iterator for Iter<'a, T> where T: 'a, { type Item = &'a T; fn next(&mut self) -> Option { self.iter.next().map(|(k, _)| k) } } pub struct Difference<'a, T, N, S> where S: 'a + BuildHasher, T: 'a + Eq + Hash, N: 'a + ArrayLength> + ArrayLength>, { iter: Iter<'a, T>, other: &'a IndexSet, } impl<'a, T, N, S> Iterator for Difference<'a, T, N, S> where S: 'a + BuildHasher, T: 'a + Eq + Hash, N: 'a + ArrayLength> + ArrayLength>, { type Item = &'a T; fn next(&mut self) -> Option { loop { let elt = self.iter.next()?; if !self.other.contains(elt) { return Some(elt); } } } } pub struct Intersection<'a, T, N, S> where S: 'a + BuildHasher, T: 'a + Eq + Hash, N: 'a + ArrayLength> + ArrayLength>, { iter: Iter<'a, T>, other: &'a IndexSet, } impl<'a, T, N, S> Iterator for Intersection<'a, T, N, S> where S: 'a + BuildHasher, T: 'a + Eq + Hash, N: 'a + ArrayLength> + ArrayLength>, { type Item = &'a T; fn next(&mut self) -> Option { loop { let elt = self.iter.next()?; if self.other.contains(elt) { return Some(elt); } } } }