diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /vendor/hashbrown-0.13.2/src | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/hashbrown-0.13.2/src')
18 files changed, 0 insertions, 17229 deletions
diff --git a/vendor/hashbrown-0.13.2/src/external_trait_impls/mod.rs b/vendor/hashbrown-0.13.2/src/external_trait_impls/mod.rs deleted file mode 100644 index ef497836c..000000000 --- a/vendor/hashbrown-0.13.2/src/external_trait_impls/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[cfg(feature = "rayon")] -pub(crate) mod rayon; -#[cfg(feature = "serde")] -mod serde; diff --git a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/helpers.rs b/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/helpers.rs deleted file mode 100644 index 070b08cd5..000000000 --- a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/helpers.rs +++ /dev/null @@ -1,27 +0,0 @@ -use alloc::collections::LinkedList; -use alloc::vec::Vec; - -use rayon::iter::{IntoParallelIterator, ParallelIterator}; - -/// Helper for collecting parallel iterators to an intermediary -#[allow(clippy::linkedlist)] // yes, we need linked list here for efficient appending! -pub(super) fn collect<I: IntoParallelIterator>(iter: I) -> (LinkedList<Vec<I::Item>>, usize) { - let list = iter - .into_par_iter() - .fold(Vec::new, |mut vec, elem| { - vec.push(elem); - vec - }) - .map(|vec| { - let mut list = LinkedList::new(); - list.push_back(vec); - list - }) - .reduce(LinkedList::new, |mut list1, mut list2| { - list1.append(&mut list2); - list1 - }); - - let len = list.iter().map(Vec::len).sum(); - (list, len) -} diff --git a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/map.rs b/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/map.rs deleted file mode 100644 index 14d91c220..000000000 --- a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/map.rs +++ /dev/null @@ -1,734 +0,0 @@ -//! Rayon extensions for `HashMap`. - -use super::raw::{RawIntoParIter, RawParDrain, RawParIter}; -use crate::hash_map::HashMap; -use crate::raw::{Allocator, Global}; -use core::fmt; -use core::hash::{BuildHasher, Hash}; -use core::marker::PhantomData; -use rayon::iter::plumbing::UnindexedConsumer; -use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; - -/// Parallel iterator over shared references to entries in a map. -/// -/// This iterator is created by the [`par_iter`] method on [`HashMap`] -/// (provided by the [`IntoParallelRefIterator`] trait). -/// See its documentation for more. -/// -/// [`par_iter`]: /hashbrown/struct.HashMap.html#method.par_iter -/// [`HashMap`]: /hashbrown/struct.HashMap.html -/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html -pub struct ParIter<'a, K, V> { - inner: RawParIter<(K, V)>, - marker: PhantomData<(&'a K, &'a V)>, -} - -impl<'a, K: Sync, V: Sync> ParallelIterator for ParIter<'a, K, V> { - type Item = (&'a K, &'a V); - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner - .map(|x| unsafe { - let r = x.as_ref(); - (&r.0, &r.1) - }) - .drive_unindexed(consumer) - } -} - -impl<K, V> Clone for ParIter<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - marker: PhantomData, - } - } -} - -impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug> fmt::Debug for ParIter<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let iter = unsafe { self.inner.iter() }.map(|x| unsafe { - let r = x.as_ref(); - (&r.0, &r.1) - }); - f.debug_list().entries(iter).finish() - } -} - -/// Parallel iterator over shared references to keys in a map. -/// -/// This iterator is created by the [`par_keys`] method on [`HashMap`]. -/// See its documentation for more. -/// -/// [`par_keys`]: /hashbrown/struct.HashMap.html#method.par_keys -/// [`HashMap`]: /hashbrown/struct.HashMap.html -pub struct ParKeys<'a, K, V> { - inner: RawParIter<(K, V)>, - marker: PhantomData<(&'a K, &'a V)>, -} - -impl<'a, K: Sync, V: Sync> ParallelIterator for ParKeys<'a, K, V> { - type Item = &'a K; - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner - .map(|x| unsafe { &x.as_ref().0 }) - .drive_unindexed(consumer) - } -} - -impl<K, V> Clone for ParKeys<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - marker: PhantomData, - } - } -} - -impl<K: fmt::Debug + Eq + Hash, V> fmt::Debug for ParKeys<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let iter = unsafe { self.inner.iter() }.map(|x| unsafe { &x.as_ref().0 }); - f.debug_list().entries(iter).finish() - } -} - -/// Parallel iterator over shared references to values in a map. -/// -/// This iterator is created by the [`par_values`] method on [`HashMap`]. -/// See its documentation for more. -/// -/// [`par_values`]: /hashbrown/struct.HashMap.html#method.par_values -/// [`HashMap`]: /hashbrown/struct.HashMap.html -pub struct ParValues<'a, K, V> { - inner: RawParIter<(K, V)>, - marker: PhantomData<(&'a K, &'a V)>, -} - -impl<'a, K: Sync, V: Sync> ParallelIterator for ParValues<'a, K, V> { - type Item = &'a V; - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner - .map(|x| unsafe { &x.as_ref().1 }) - .drive_unindexed(consumer) - } -} - -impl<K, V> Clone for ParValues<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - marker: PhantomData, - } - } -} - -impl<K: Eq + Hash, V: fmt::Debug> fmt::Debug for ParValues<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let iter = unsafe { self.inner.iter() }.map(|x| unsafe { &x.as_ref().1 }); - f.debug_list().entries(iter).finish() - } -} - -/// Parallel iterator over mutable references to entries in a map. -/// -/// This iterator is created by the [`par_iter_mut`] method on [`HashMap`] -/// (provided by the [`IntoParallelRefMutIterator`] trait). -/// See its documentation for more. -/// -/// [`par_iter_mut`]: /hashbrown/struct.HashMap.html#method.par_iter_mut -/// [`HashMap`]: /hashbrown/struct.HashMap.html -/// [`IntoParallelRefMutIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefMutIterator.html -pub struct ParIterMut<'a, K, V> { - inner: RawParIter<(K, V)>, - marker: PhantomData<(&'a K, &'a mut V)>, -} - -impl<'a, K: Sync, V: Send> ParallelIterator for ParIterMut<'a, K, V> { - type Item = (&'a K, &'a mut V); - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner - .map(|x| unsafe { - let r = x.as_mut(); - (&r.0, &mut r.1) - }) - .drive_unindexed(consumer) - } -} - -impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug> fmt::Debug for ParIterMut<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ParIter { - inner: self.inner.clone(), - marker: PhantomData, - } - .fmt(f) - } -} - -/// Parallel iterator over mutable references to values in a map. -/// -/// This iterator is created by the [`par_values_mut`] method on [`HashMap`]. -/// See its documentation for more. -/// -/// [`par_values_mut`]: /hashbrown/struct.HashMap.html#method.par_values_mut -/// [`HashMap`]: /hashbrown/struct.HashMap.html -pub struct ParValuesMut<'a, K, V> { - inner: RawParIter<(K, V)>, - marker: PhantomData<(&'a K, &'a mut V)>, -} - -impl<'a, K: Sync, V: Send> ParallelIterator for ParValuesMut<'a, K, V> { - type Item = &'a mut V; - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner - .map(|x| unsafe { &mut x.as_mut().1 }) - .drive_unindexed(consumer) - } -} - -impl<K: Eq + Hash, V: fmt::Debug> fmt::Debug for ParValuesMut<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ParValues { - inner: self.inner.clone(), - marker: PhantomData, - } - .fmt(f) - } -} - -/// Parallel iterator over entries of a consumed map. -/// -/// This iterator is created by the [`into_par_iter`] method on [`HashMap`] -/// (provided by the [`IntoParallelIterator`] trait). -/// See its documentation for more. -/// -/// [`into_par_iter`]: /hashbrown/struct.HashMap.html#method.into_par_iter -/// [`HashMap`]: /hashbrown/struct.HashMap.html -/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html -pub struct IntoParIter<K, V, A: Allocator + Clone = Global> { - inner: RawIntoParIter<(K, V), A>, -} - -impl<K: Send, V: Send, A: Allocator + Clone + Send> ParallelIterator for IntoParIter<K, V, A> { - type Item = (K, V); - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner.drive_unindexed(consumer) - } -} - -impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator + Clone> fmt::Debug - for IntoParIter<K, V, A> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ParIter { - inner: unsafe { self.inner.par_iter() }, - marker: PhantomData, - } - .fmt(f) - } -} - -/// Parallel draining iterator over entries of a map. -/// -/// This iterator is created by the [`par_drain`] method on [`HashMap`]. -/// See its documentation for more. -/// -/// [`par_drain`]: /hashbrown/struct.HashMap.html#method.par_drain -/// [`HashMap`]: /hashbrown/struct.HashMap.html -pub struct ParDrain<'a, K, V, A: Allocator + Clone = Global> { - inner: RawParDrain<'a, (K, V), A>, -} - -impl<K: Send, V: Send, A: Allocator + Clone + Sync> ParallelIterator for ParDrain<'_, K, V, A> { - type Item = (K, V); - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner.drive_unindexed(consumer) - } -} - -impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator + Clone> fmt::Debug - for ParDrain<'_, K, V, A> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ParIter { - inner: unsafe { self.inner.par_iter() }, - marker: PhantomData, - } - .fmt(f) - } -} - -impl<K: Sync, V: Sync, S, A: Allocator + Clone> HashMap<K, V, S, A> { - /// Visits (potentially in parallel) immutably borrowed keys in an arbitrary order. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_keys(&self) -> ParKeys<'_, K, V> { - ParKeys { - inner: unsafe { self.table.par_iter() }, - marker: PhantomData, - } - } - - /// Visits (potentially in parallel) immutably borrowed values in an arbitrary order. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_values(&self) -> ParValues<'_, K, V> { - ParValues { - inner: unsafe { self.table.par_iter() }, - marker: PhantomData, - } - } -} - -impl<K: Send, V: Send, S, A: Allocator + Clone> HashMap<K, V, S, A> { - /// Visits (potentially in parallel) mutably borrowed values in an arbitrary order. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V> { - ParValuesMut { - inner: unsafe { self.table.par_iter() }, - marker: PhantomData, - } - } - - /// Consumes (potentially in parallel) all values in an arbitrary order, - /// while preserving the map's allocated memory for reuse. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_drain(&mut self) -> ParDrain<'_, K, V, A> { - ParDrain { - inner: self.table.par_drain(), - } - } -} - -impl<K, V, S, A> HashMap<K, V, S, A> -where - K: Eq + Hash + Sync, - V: PartialEq + Sync, - S: BuildHasher + Sync, - A: Allocator + Clone + Sync, -{ - /// Returns `true` if the map is equal to another, - /// i.e. both maps contain the same keys mapped to the same values. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_eq(&self, other: &Self) -> bool { - self.len() == other.len() - && self - .into_par_iter() - .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) - } -} - -impl<K: Send, V: Send, S, A: Allocator + Clone + Send> IntoParallelIterator - for HashMap<K, V, S, A> -{ - type Item = (K, V); - type Iter = IntoParIter<K, V, A>; - - #[cfg_attr(feature = "inline-more", inline)] - fn into_par_iter(self) -> Self::Iter { - IntoParIter { - inner: self.table.into_par_iter(), - } - } -} - -impl<'a, K: Sync, V: Sync, S, A: Allocator + Clone> IntoParallelIterator - for &'a HashMap<K, V, S, A> -{ - type Item = (&'a K, &'a V); - type Iter = ParIter<'a, K, V>; - - #[cfg_attr(feature = "inline-more", inline)] - fn into_par_iter(self) -> Self::Iter { - ParIter { - inner: unsafe { self.table.par_iter() }, - marker: PhantomData, - } - } -} - -impl<'a, K: Sync, V: Send, S, A: Allocator + Clone> IntoParallelIterator - for &'a mut HashMap<K, V, S, A> -{ - type Item = (&'a K, &'a mut V); - type Iter = ParIterMut<'a, K, V>; - - #[cfg_attr(feature = "inline-more", inline)] - fn into_par_iter(self) -> Self::Iter { - ParIterMut { - inner: unsafe { self.table.par_iter() }, - marker: PhantomData, - } - } -} - -/// Collect (key, value) pairs from a parallel iterator into a -/// hashmap. If multiple pairs correspond to the same key, then the -/// ones produced earlier in the parallel iterator will be -/// overwritten, just as with a sequential iterator. -impl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S, Global> -where - K: Eq + Hash + Send, - V: Send, - S: BuildHasher + Default, -{ - fn from_par_iter<P>(par_iter: P) -> Self - where - P: IntoParallelIterator<Item = (K, V)>, - { - let mut map = HashMap::default(); - map.par_extend(par_iter); - map - } -} - -/// Extend a hash map with items from a parallel iterator. -impl<K, V, S, A> ParallelExtend<(K, V)> for HashMap<K, V, S, A> -where - K: Eq + Hash + Send, - V: Send, - S: BuildHasher, - A: Allocator + Clone, -{ - fn par_extend<I>(&mut self, par_iter: I) - where - I: IntoParallelIterator<Item = (K, V)>, - { - extend(self, par_iter); - } -} - -/// Extend a hash map with copied items from a parallel iterator. -impl<'a, K, V, S, A> ParallelExtend<(&'a K, &'a V)> for HashMap<K, V, S, A> -where - K: Copy + Eq + Hash + Sync, - V: Copy + Sync, - S: BuildHasher, - A: Allocator + Clone, -{ - fn par_extend<I>(&mut self, par_iter: I) - where - I: IntoParallelIterator<Item = (&'a K, &'a V)>, - { - extend(self, par_iter); - } -} - -// This is equal to the normal `HashMap` -- no custom advantage. -fn extend<K, V, S, A, I>(map: &mut HashMap<K, V, S, A>, par_iter: I) -where - K: Eq + Hash, - S: BuildHasher, - I: IntoParallelIterator, - A: Allocator + Clone, - HashMap<K, V, S, A>: Extend<I::Item>, -{ - let (list, len) = super::helpers::collect(par_iter); - - // Keys may be already present or show multiple times in the iterator. - // Reserve the entire length if the map is empty. - // Otherwise reserve half the length (rounded up), so the map - // will only resize twice in the worst case. - let reserve = if map.is_empty() { len } else { (len + 1) / 2 }; - map.reserve(reserve); - for vec in list { - map.extend(vec); - } -} - -#[cfg(test)] -mod test_par_map { - use alloc::vec::Vec; - use core::hash::{Hash, Hasher}; - use core::sync::atomic::{AtomicUsize, Ordering}; - - use rayon::prelude::*; - - use crate::hash_map::HashMap; - - struct Dropable<'a> { - k: usize, - counter: &'a AtomicUsize, - } - - impl Dropable<'_> { - fn new(k: usize, counter: &AtomicUsize) -> Dropable<'_> { - counter.fetch_add(1, Ordering::Relaxed); - - Dropable { k, counter } - } - } - - impl Drop for Dropable<'_> { - fn drop(&mut self) { - self.counter.fetch_sub(1, Ordering::Relaxed); - } - } - - impl Clone for Dropable<'_> { - fn clone(&self) -> Self { - Dropable::new(self.k, self.counter) - } - } - - impl Hash for Dropable<'_> { - fn hash<H>(&self, state: &mut H) - where - H: Hasher, - { - self.k.hash(state); - } - } - - impl PartialEq for Dropable<'_> { - fn eq(&self, other: &Self) -> bool { - self.k == other.k - } - } - - impl Eq for Dropable<'_> {} - - #[test] - fn test_into_iter_drops() { - let key = AtomicUsize::new(0); - let value = AtomicUsize::new(0); - - let hm = { - let mut hm = HashMap::new(); - - assert_eq!(key.load(Ordering::Relaxed), 0); - assert_eq!(value.load(Ordering::Relaxed), 0); - - for i in 0..100 { - let d1 = Dropable::new(i, &key); - let d2 = Dropable::new(i + 100, &value); - hm.insert(d1, d2); - } - - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - hm - }; - - // By the way, ensure that cloning doesn't screw up the dropping. - drop(hm.clone()); - - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - // Ensure that dropping the iterator does not leak anything. - drop(hm.clone().into_par_iter()); - - { - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - // retain only half - let _v: Vec<_> = hm - .into_par_iter() - .filter(|&(ref key, _)| key.k < 50) - .collect(); - - assert_eq!(key.load(Ordering::Relaxed), 50); - assert_eq!(value.load(Ordering::Relaxed), 50); - }; - - assert_eq!(key.load(Ordering::Relaxed), 0); - assert_eq!(value.load(Ordering::Relaxed), 0); - } - - #[test] - fn test_drain_drops() { - let key = AtomicUsize::new(0); - let value = AtomicUsize::new(0); - - let mut hm = { - let mut hm = HashMap::new(); - - assert_eq!(key.load(Ordering::Relaxed), 0); - assert_eq!(value.load(Ordering::Relaxed), 0); - - for i in 0..100 { - let d1 = Dropable::new(i, &key); - let d2 = Dropable::new(i + 100, &value); - hm.insert(d1, d2); - } - - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - hm - }; - - // By the way, ensure that cloning doesn't screw up the dropping. - drop(hm.clone()); - - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - // Ensure that dropping the drain iterator does not leak anything. - drop(hm.clone().par_drain()); - - { - assert_eq!(key.load(Ordering::Relaxed), 100); - assert_eq!(value.load(Ordering::Relaxed), 100); - - // retain only half - let _v: Vec<_> = hm.drain().filter(|&(ref key, _)| key.k < 50).collect(); - assert!(hm.is_empty()); - - assert_eq!(key.load(Ordering::Relaxed), 50); - assert_eq!(value.load(Ordering::Relaxed), 50); - }; - - assert_eq!(key.load(Ordering::Relaxed), 0); - assert_eq!(value.load(Ordering::Relaxed), 0); - } - - #[test] - fn test_empty_iter() { - let mut m: HashMap<isize, bool> = HashMap::new(); - assert_eq!(m.par_drain().count(), 0); - assert_eq!(m.par_keys().count(), 0); - assert_eq!(m.par_values().count(), 0); - assert_eq!(m.par_values_mut().count(), 0); - assert_eq!(m.par_iter().count(), 0); - assert_eq!(m.par_iter_mut().count(), 0); - assert_eq!(m.len(), 0); - assert!(m.is_empty()); - assert_eq!(m.into_par_iter().count(), 0); - } - - #[test] - fn test_iterate() { - let mut m = HashMap::with_capacity(4); - for i in 0..32 { - assert!(m.insert(i, i * 2).is_none()); - } - assert_eq!(m.len(), 32); - - let observed = AtomicUsize::new(0); - - m.par_iter().for_each(|(k, v)| { - assert_eq!(*v, *k * 2); - observed.fetch_or(1 << *k, Ordering::Relaxed); - }); - assert_eq!(observed.into_inner(), 0xFFFF_FFFF); - } - - #[test] - fn test_keys() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_par_iter().collect(); - let keys: Vec<_> = map.par_keys().cloned().collect(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_par_iter().collect(); - let values: Vec<_> = map.par_values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_values_mut() { - let vec = vec![(1, 1), (2, 2), (3, 3)]; - let mut map: HashMap<_, _> = vec.into_par_iter().collect(); - map.par_values_mut().for_each(|value| *value *= 2); - let values: Vec<_> = map.par_values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&2)); - assert!(values.contains(&4)); - assert!(values.contains(&6)); - } - - #[test] - fn test_eq() { - let mut m1 = HashMap::new(); - m1.insert(1, 2); - m1.insert(2, 3); - m1.insert(3, 4); - - let mut m2 = HashMap::new(); - m2.insert(1, 2); - m2.insert(2, 3); - - assert!(!m1.par_eq(&m2)); - - m2.insert(3, 4); - - assert!(m1.par_eq(&m2)); - } - - #[test] - fn test_from_iter() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.par_iter().cloned().collect(); - - for &(k, v) in &xs { - assert_eq!(map.get(&k), Some(&v)); - } - } - - #[test] - fn test_extend_ref() { - let mut a = HashMap::new(); - a.insert(1, "one"); - let mut b = HashMap::new(); - b.insert(2, "two"); - b.insert(3, "three"); - - a.par_extend(&b); - - assert_eq!(a.len(), 3); - assert_eq!(a[&1], "one"); - assert_eq!(a[&2], "two"); - assert_eq!(a[&3], "three"); - } -} diff --git a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/mod.rs b/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/mod.rs deleted file mode 100644 index 99337a1ce..000000000 --- a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -mod helpers; -pub(crate) mod map; -pub(crate) mod raw; -pub(crate) mod set; diff --git a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/raw.rs b/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/raw.rs deleted file mode 100644 index 883303e27..000000000 --- a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/raw.rs +++ /dev/null @@ -1,231 +0,0 @@ -use crate::raw::Bucket; -use crate::raw::{Allocator, Global, RawIter, RawIterRange, RawTable}; -use crate::scopeguard::guard; -use alloc::alloc::dealloc; -use core::marker::PhantomData; -use core::mem; -use core::ptr::NonNull; -use rayon::iter::{ - plumbing::{self, Folder, UnindexedConsumer, UnindexedProducer}, - ParallelIterator, -}; - -/// Parallel iterator which returns a raw pointer to every full bucket in the table. -pub struct RawParIter<T> { - iter: RawIterRange<T>, -} - -impl<T> RawParIter<T> { - #[cfg_attr(feature = "inline-more", inline)] - pub(super) unsafe fn iter(&self) -> RawIterRange<T> { - self.iter.clone() - } -} - -impl<T> Clone for RawParIter<T> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Self { - iter: self.iter.clone(), - } - } -} - -impl<T> From<RawIter<T>> for RawParIter<T> { - fn from(it: RawIter<T>) -> Self { - RawParIter { iter: it.iter } - } -} - -impl<T> ParallelIterator for RawParIter<T> { - type Item = Bucket<T>; - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - let producer = ParIterProducer { iter: self.iter }; - plumbing::bridge_unindexed(producer, consumer) - } -} - -/// Producer which returns a `Bucket<T>` for every element. -struct ParIterProducer<T> { - iter: RawIterRange<T>, -} - -impl<T> UnindexedProducer for ParIterProducer<T> { - type Item = Bucket<T>; - - #[cfg_attr(feature = "inline-more", inline)] - fn split(self) -> (Self, Option<Self>) { - let (left, right) = self.iter.split(); - let left = ParIterProducer { iter: left }; - let right = right.map(|right| ParIterProducer { iter: right }); - (left, right) - } - - #[cfg_attr(feature = "inline-more", inline)] - fn fold_with<F>(self, folder: F) -> F - where - F: Folder<Self::Item>, - { - folder.consume_iter(self.iter) - } -} - -/// Parallel iterator which consumes a table and returns elements. -pub struct RawIntoParIter<T, A: Allocator + Clone = Global> { - table: RawTable<T, A>, -} - -impl<T, A: Allocator + Clone> RawIntoParIter<T, A> { - #[cfg_attr(feature = "inline-more", inline)] - pub(super) unsafe fn par_iter(&self) -> RawParIter<T> { - self.table.par_iter() - } -} - -impl<T: Send, A: Allocator + Clone + Send> ParallelIterator for RawIntoParIter<T, A> { - type Item = T; - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - let iter = unsafe { self.table.iter().iter }; - let _guard = guard(self.table.into_allocation(), |alloc| { - if let Some((ptr, layout)) = *alloc { - unsafe { - dealloc(ptr.as_ptr(), layout); - } - } - }); - let producer = ParDrainProducer { iter }; - plumbing::bridge_unindexed(producer, consumer) - } -} - -/// Parallel iterator which consumes elements without freeing the table storage. -pub struct RawParDrain<'a, T, A: Allocator + Clone = Global> { - // We don't use a &'a mut RawTable<T> because we want RawParDrain to be - // covariant over T. - table: NonNull<RawTable<T, A>>, - marker: PhantomData<&'a RawTable<T, A>>, -} - -unsafe impl<T: Send, A: Allocator + Clone> Send for RawParDrain<'_, T, A> {} - -impl<T, A: Allocator + Clone> RawParDrain<'_, T, A> { - #[cfg_attr(feature = "inline-more", inline)] - pub(super) unsafe fn par_iter(&self) -> RawParIter<T> { - self.table.as_ref().par_iter() - } -} - -impl<T: Send, A: Allocator + Clone> ParallelIterator for RawParDrain<'_, T, A> { - type Item = T; - - #[cfg_attr(feature = "inline-more", inline)] - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - let _guard = guard(self.table, |table| unsafe { - table.as_mut().clear_no_drop(); - }); - let iter = unsafe { self.table.as_ref().iter().iter }; - mem::forget(self); - let producer = ParDrainProducer { iter }; - plumbing::bridge_unindexed(producer, consumer) - } -} - -impl<T, A: Allocator + Clone> Drop for RawParDrain<'_, T, A> { - fn drop(&mut self) { - // If drive_unindexed is not called then simply clear the table. - unsafe { - self.table.as_mut().clear(); - } - } -} - -/// Producer which will consume all elements in the range, even if it is dropped -/// halfway through. -struct ParDrainProducer<T> { - iter: RawIterRange<T>, -} - -impl<T: Send> UnindexedProducer for ParDrainProducer<T> { - type Item = T; - - #[cfg_attr(feature = "inline-more", inline)] - fn split(self) -> (Self, Option<Self>) { - let (left, right) = self.iter.clone().split(); - mem::forget(self); - let left = ParDrainProducer { iter: left }; - let right = right.map(|right| ParDrainProducer { iter: right }); - (left, right) - } - - #[cfg_attr(feature = "inline-more", inline)] - fn fold_with<F>(mut self, mut folder: F) -> F - where - F: Folder<Self::Item>, - { - // Make sure to modify the iterator in-place so that any remaining - // elements are processed in our Drop impl. - for item in &mut self.iter { - folder = folder.consume(unsafe { item.read() }); - if folder.full() { - return folder; - } - } - - // If we processed all elements then we don't need to run the drop. - mem::forget(self); - folder - } -} - -impl<T> Drop for ParDrainProducer<T> { - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - // Drop all remaining elements - if mem::needs_drop::<T>() { - for item in &mut self.iter { - unsafe { - item.drop(); - } - } - } - } -} - -impl<T, A: Allocator + Clone> RawTable<T, A> { - /// Returns a parallel iterator over the elements in a `RawTable`. - #[cfg_attr(feature = "inline-more", inline)] - pub unsafe fn par_iter(&self) -> RawParIter<T> { - RawParIter { - iter: self.iter().iter, - } - } - - /// Returns a parallel iterator over the elements in a `RawTable`. - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_par_iter(self) -> RawIntoParIter<T, A> { - RawIntoParIter { table: self } - } - - /// Returns a parallel iterator which consumes all elements of a `RawTable` - /// without freeing its memory allocation. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_drain(&mut self) -> RawParDrain<'_, T, A> { - RawParDrain { - table: NonNull::from(self), - marker: PhantomData, - } - } -} diff --git a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/set.rs b/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/set.rs deleted file mode 100644 index ee4f6e669..000000000 --- a/vendor/hashbrown-0.13.2/src/external_trait_impls/rayon/set.rs +++ /dev/null @@ -1,659 +0,0 @@ -//! Rayon extensions for `HashSet`. - -use super::map; -use crate::hash_set::HashSet; -use crate::raw::{Allocator, Global}; -use core::hash::{BuildHasher, Hash}; -use rayon::iter::plumbing::UnindexedConsumer; -use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; - -/// Parallel iterator over elements of a consumed set. -/// -/// This iterator is created by the [`into_par_iter`] method on [`HashSet`] -/// (provided by the [`IntoParallelIterator`] trait). -/// See its documentation for more. -/// -/// [`into_par_iter`]: /hashbrown/struct.HashSet.html#method.into_par_iter -/// [`HashSet`]: /hashbrown/struct.HashSet.html -/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html -pub struct IntoParIter<T, A: Allocator + Clone = Global> { - inner: map::IntoParIter<T, (), A>, -} - -impl<T: Send, A: Allocator + Clone + Send> ParallelIterator for IntoParIter<T, A> { - type Item = T; - - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner.map(|(k, _)| k).drive_unindexed(consumer) - } -} - -/// Parallel draining iterator over entries of a set. -/// -/// This iterator is created by the [`par_drain`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_drain`]: /hashbrown/struct.HashSet.html#method.par_drain -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParDrain<'a, T, A: Allocator + Clone = Global> { - inner: map::ParDrain<'a, T, (), A>, -} - -impl<T: Send, A: Allocator + Clone + Send + Sync> ParallelIterator for ParDrain<'_, T, A> { - type Item = T; - - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner.map(|(k, _)| k).drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in a set. -/// -/// This iterator is created by the [`par_iter`] method on [`HashSet`] -/// (provided by the [`IntoParallelRefIterator`] trait). -/// See its documentation for more. -/// -/// [`par_iter`]: /hashbrown/struct.HashSet.html#method.par_iter -/// [`HashSet`]: /hashbrown/struct.HashSet.html -/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html -pub struct ParIter<'a, T> { - inner: map::ParKeys<'a, T, ()>, -} - -impl<'a, T: Sync> ParallelIterator for ParIter<'a, T> { - type Item = &'a T; - - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.inner.drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in the difference of -/// sets. -/// -/// This iterator is created by the [`par_difference`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_difference`]: /hashbrown/struct.HashSet.html#method.par_difference -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParDifference<'a, T, S, A: Allocator + Clone = Global> { - a: &'a HashSet<T, S, A>, - b: &'a HashSet<T, S, A>, -} - -impl<'a, T, S, A> ParallelIterator for ParDifference<'a, T, S, A> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, - A: Allocator + Clone + Sync, -{ - type Item = &'a T; - - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.a - .into_par_iter() - .filter(|&x| !self.b.contains(x)) - .drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in the symmetric -/// difference of sets. -/// -/// This iterator is created by the [`par_symmetric_difference`] method on -/// [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_symmetric_difference`]: /hashbrown/struct.HashSet.html#method.par_symmetric_difference -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParSymmetricDifference<'a, T, S, A: Allocator + Clone = Global> { - a: &'a HashSet<T, S, A>, - b: &'a HashSet<T, S, A>, -} - -impl<'a, T, S, A> ParallelIterator for ParSymmetricDifference<'a, T, S, A> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, - A: Allocator + Clone + Sync, -{ - type Item = &'a T; - - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.a - .par_difference(self.b) - .chain(self.b.par_difference(self.a)) - .drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in the intersection of -/// sets. -/// -/// This iterator is created by the [`par_intersection`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_intersection`]: /hashbrown/struct.HashSet.html#method.par_intersection -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParIntersection<'a, T, S, A: Allocator + Clone = Global> { - a: &'a HashSet<T, S, A>, - b: &'a HashSet<T, S, A>, -} - -impl<'a, T, S, A> ParallelIterator for ParIntersection<'a, T, S, A> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, - A: Allocator + Clone + Sync, -{ - type Item = &'a T; - - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - self.a - .into_par_iter() - .filter(|&x| self.b.contains(x)) - .drive_unindexed(consumer) - } -} - -/// Parallel iterator over shared references to elements in the union of sets. -/// -/// This iterator is created by the [`par_union`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`par_union`]: /hashbrown/struct.HashSet.html#method.par_union -/// [`HashSet`]: /hashbrown/struct.HashSet.html -pub struct ParUnion<'a, T, S, A: Allocator + Clone = Global> { - a: &'a HashSet<T, S, A>, - b: &'a HashSet<T, S, A>, -} - -impl<'a, T, S, A> ParallelIterator for ParUnion<'a, T, S, A> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, - A: Allocator + Clone + Sync, -{ - type Item = &'a T; - - fn drive_unindexed<C>(self, consumer: C) -> C::Result - where - C: UnindexedConsumer<Self::Item>, - { - // We'll iterate one set in full, and only the remaining difference from the other. - // Use the smaller set for the difference in order to reduce hash lookups. - let (smaller, larger) = if self.a.len() <= self.b.len() { - (self.a, self.b) - } else { - (self.b, self.a) - }; - larger - .into_par_iter() - .chain(smaller.par_difference(larger)) - .drive_unindexed(consumer) - } -} - -impl<T, S, A> HashSet<T, S, A> -where - T: Eq + Hash + Sync, - S: BuildHasher + Sync, - A: Allocator + Clone + Sync, -{ - /// Visits (potentially in parallel) the values representing the union, - /// i.e. all the values in `self` or `other`, without duplicates. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_union<'a>(&'a self, other: &'a Self) -> ParUnion<'a, T, S, A> { - ParUnion { a: self, b: other } - } - - /// Visits (potentially in parallel) the values representing the difference, - /// i.e. the values that are in `self` but not in `other`. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_difference<'a>(&'a self, other: &'a Self) -> ParDifference<'a, T, S, A> { - ParDifference { a: self, b: other } - } - - /// Visits (potentially in parallel) the values representing the symmetric - /// difference, i.e. the values that are in `self` or in `other` but not in both. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_symmetric_difference<'a>( - &'a self, - other: &'a Self, - ) -> ParSymmetricDifference<'a, T, S, A> { - ParSymmetricDifference { a: self, b: other } - } - - /// Visits (potentially in parallel) the values representing the - /// intersection, i.e. the values that are both in `self` and `other`. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_intersection<'a>(&'a self, other: &'a Self) -> ParIntersection<'a, T, S, A> { - ParIntersection { a: self, b: other } - } - - /// Returns `true` if `self` has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_is_disjoint(&self, other: &Self) -> bool { - self.into_par_iter().all(|x| !other.contains(x)) - } - - /// Returns `true` if the set is a subset of another, - /// i.e. `other` contains at least all the values in `self`. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_is_subset(&self, other: &Self) -> bool { - if self.len() <= other.len() { - self.into_par_iter().all(|x| other.contains(x)) - } else { - false - } - } - - /// Returns `true` if the set is a superset of another, - /// i.e. `self` contains at least all the values in `other`. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_is_superset(&self, other: &Self) -> bool { - other.par_is_subset(self) - } - - /// Returns `true` if the set is equal to another, - /// i.e. both sets contain the same values. - /// - /// This method runs in a potentially parallel fashion. - pub fn par_eq(&self, other: &Self) -> bool { - self.len() == other.len() && self.par_is_subset(other) - } -} - -impl<T, S, A> HashSet<T, S, A> -where - T: Eq + Hash + Send, - A: Allocator + Clone + Send, -{ - /// Consumes (potentially in parallel) all values in an arbitrary order, - /// while preserving the set's allocated memory for reuse. - #[cfg_attr(feature = "inline-more", inline)] - pub fn par_drain(&mut self) -> ParDrain<'_, T, A> { - ParDrain { - inner: self.map.par_drain(), - } - } -} - -impl<T: Send, S, A: Allocator + Clone + Send> IntoParallelIterator for HashSet<T, S, A> { - type Item = T; - type Iter = IntoParIter<T, A>; - - #[cfg_attr(feature = "inline-more", inline)] - fn into_par_iter(self) -> Self::Iter { - IntoParIter { - inner: self.map.into_par_iter(), - } - } -} - -impl<'a, T: Sync, S, A: Allocator + Clone> IntoParallelIterator for &'a HashSet<T, S, A> { - type Item = &'a T; - type Iter = ParIter<'a, T>; - - #[cfg_attr(feature = "inline-more", inline)] - fn into_par_iter(self) -> Self::Iter { - ParIter { - inner: self.map.par_keys(), - } - } -} - -/// Collect values from a parallel iterator into a hashset. -impl<T, S> FromParallelIterator<T> for HashSet<T, S, Global> -where - T: Eq + Hash + Send, - S: BuildHasher + Default, -{ - fn from_par_iter<P>(par_iter: P) -> Self - where - P: IntoParallelIterator<Item = T>, - { - let mut set = HashSet::default(); - set.par_extend(par_iter); - set - } -} - -/// Extend a hash set with items from a parallel iterator. -impl<T, S> ParallelExtend<T> for HashSet<T, S, Global> -where - T: Eq + Hash + Send, - S: BuildHasher, -{ - fn par_extend<I>(&mut self, par_iter: I) - where - I: IntoParallelIterator<Item = T>, - { - extend(self, par_iter); - } -} - -/// Extend a hash set with copied items from a parallel iterator. -impl<'a, T, S> ParallelExtend<&'a T> for HashSet<T, S, Global> -where - T: 'a + Copy + Eq + Hash + Sync, - S: BuildHasher, -{ - fn par_extend<I>(&mut self, par_iter: I) - where - I: IntoParallelIterator<Item = &'a T>, - { - extend(self, par_iter); - } -} - -// This is equal to the normal `HashSet` -- no custom advantage. -fn extend<T, S, I, A>(set: &mut HashSet<T, S, A>, par_iter: I) -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, - I: IntoParallelIterator, - HashSet<T, S, A>: Extend<I::Item>, -{ - let (list, len) = super::helpers::collect(par_iter); - - // Values may be already present or show multiple times in the iterator. - // Reserve the entire length if the set is empty. - // Otherwise reserve half the length (rounded up), so the set - // will only resize twice in the worst case. - let reserve = if set.is_empty() { len } else { (len + 1) / 2 }; - set.reserve(reserve); - for vec in list { - set.extend(vec); - } -} - -#[cfg(test)] -mod test_par_set { - use alloc::vec::Vec; - use core::sync::atomic::{AtomicUsize, Ordering}; - - use rayon::prelude::*; - - use crate::hash_set::HashSet; - - #[test] - fn test_disjoint() { - let mut xs = HashSet::new(); - let mut ys = HashSet::new(); - assert!(xs.par_is_disjoint(&ys)); - assert!(ys.par_is_disjoint(&xs)); - assert!(xs.insert(5)); - assert!(ys.insert(11)); - assert!(xs.par_is_disjoint(&ys)); - assert!(ys.par_is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.par_is_disjoint(&ys)); - assert!(ys.par_is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.par_is_disjoint(&ys)); - assert!(!ys.par_is_disjoint(&xs)); - } - - #[test] - fn test_subset_and_superset() { - let mut a = HashSet::new(); - assert!(a.insert(0)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = HashSet::new(); - assert!(b.insert(0)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.par_is_subset(&b)); - assert!(!a.par_is_superset(&b)); - assert!(!b.par_is_subset(&a)); - assert!(!b.par_is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.par_is_subset(&b)); - assert!(!a.par_is_superset(&b)); - assert!(!b.par_is_subset(&a)); - assert!(b.par_is_superset(&a)); - } - - #[test] - fn test_iterate() { - let mut a = HashSet::new(); - for i in 0..32 { - assert!(a.insert(i)); - } - let observed = AtomicUsize::new(0); - a.par_iter().for_each(|k| { - observed.fetch_or(1 << *k, Ordering::Relaxed); - }); - assert_eq!(observed.into_inner(), 0xFFFF_FFFF); - } - - #[test] - fn test_intersection() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - assert!(a.insert(-5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(-9)); - assert!(b.insert(-42)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let expected = [3, 5, 11, 77]; - let i = a - .par_intersection(&b) - .map(|x| { - assert!(expected.contains(x)); - 1 - }) - .sum::<usize>(); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - - let expected = [1, 5, 11]; - let i = a - .par_difference(&b) - .map(|x| { - assert!(expected.contains(x)); - 1 - }) - .sum::<usize>(); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_symmetric_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(-2)); - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(22)); - - let expected = [-2, 1, 5, 11, 14, 22]; - let i = a - .par_symmetric_difference(&b) - .map(|x| { - assert!(expected.contains(x)); - 1 - }) - .sum::<usize>(); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_union() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(16)); - assert!(a.insert(19)); - assert!(a.insert(24)); - - assert!(b.insert(-2)); - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; - let i = a - .par_union(&b) - .map(|x| { - assert!(expected.contains(x)); - 1 - }) - .sum::<usize>(); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_from_iter() { - let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: HashSet<_> = xs.par_iter().cloned().collect(); - - for x in &xs { - assert!(set.contains(x)); - } - } - - #[test] - fn test_move_iter() { - let hs = { - let mut hs = HashSet::new(); - - hs.insert('a'); - hs.insert('b'); - - hs - }; - - let v = hs.into_par_iter().collect::<Vec<char>>(); - assert!(v == ['a', 'b'] || v == ['b', 'a']); - } - - #[test] - fn test_eq() { - // These constants once happened to expose a bug in insert(). - // I'm keeping them around to prevent a regression. - let mut s1 = HashSet::new(); - - s1.insert(1); - s1.insert(2); - s1.insert(3); - - let mut s2 = HashSet::new(); - - s2.insert(1); - s2.insert(2); - - assert!(!s1.par_eq(&s2)); - - s2.insert(3); - - assert!(s1.par_eq(&s2)); - } - - #[test] - fn test_extend_ref() { - let mut a = HashSet::new(); - a.insert(1); - - a.par_extend(&[2, 3, 4][..]); - - assert_eq!(a.len(), 4); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - - let mut b = HashSet::new(); - b.insert(5); - b.insert(6); - - a.par_extend(&b); - - assert_eq!(a.len(), 6); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - assert!(a.contains(&5)); - assert!(a.contains(&6)); - } -} diff --git a/vendor/hashbrown-0.13.2/src/external_trait_impls/serde.rs b/vendor/hashbrown-0.13.2/src/external_trait_impls/serde.rs deleted file mode 100644 index 4d62deeb7..000000000 --- a/vendor/hashbrown-0.13.2/src/external_trait_impls/serde.rs +++ /dev/null @@ -1,201 +0,0 @@ -mod size_hint { - use core::cmp; - - /// This presumably exists to prevent denial of service attacks. - /// - /// Original discussion: https://github.com/serde-rs/serde/issues/1114. - #[cfg_attr(feature = "inline-more", inline)] - pub(super) fn cautious(hint: Option<usize>) -> usize { - cmp::min(hint.unwrap_or(0), 4096) - } -} - -mod map { - use core::fmt; - use core::hash::{BuildHasher, Hash}; - use core::marker::PhantomData; - use serde::de::{Deserialize, Deserializer, MapAccess, Visitor}; - use serde::ser::{Serialize, Serializer}; - - use crate::hash_map::HashMap; - - use super::size_hint; - - impl<K, V, H> Serialize for HashMap<K, V, H> - where - K: Serialize + Eq + Hash, - V: Serialize, - H: BuildHasher, - { - #[cfg_attr(feature = "inline-more", inline)] - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - serializer.collect_map(self) - } - } - - impl<'de, K, V, S> Deserialize<'de> for HashMap<K, V, S> - where - K: Deserialize<'de> + Eq + Hash, - V: Deserialize<'de>, - S: BuildHasher + Default, - { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: Deserializer<'de>, - { - struct MapVisitor<K, V, S> { - marker: PhantomData<HashMap<K, V, S>>, - } - - impl<'de, K, V, S> Visitor<'de> for MapVisitor<K, V, S> - where - K: Deserialize<'de> + Eq + Hash, - V: Deserialize<'de>, - S: BuildHasher + Default, - { - type Value = HashMap<K, V, S>; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a map") - } - - #[cfg_attr(feature = "inline-more", inline)] - fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> - where - A: MapAccess<'de>, - { - let mut values = HashMap::with_capacity_and_hasher( - size_hint::cautious(map.size_hint()), - S::default(), - ); - - while let Some((key, value)) = map.next_entry()? { - values.insert(key, value); - } - - Ok(values) - } - } - - let visitor = MapVisitor { - marker: PhantomData, - }; - deserializer.deserialize_map(visitor) - } - } -} - -mod set { - use core::fmt; - use core::hash::{BuildHasher, Hash}; - use core::marker::PhantomData; - use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; - use serde::ser::{Serialize, Serializer}; - - use crate::hash_set::HashSet; - - use super::size_hint; - - impl<T, H> Serialize for HashSet<T, H> - where - T: Serialize + Eq + Hash, - H: BuildHasher, - { - #[cfg_attr(feature = "inline-more", inline)] - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - serializer.collect_seq(self) - } - } - - impl<'de, T, S> Deserialize<'de> for HashSet<T, S> - where - T: Deserialize<'de> + Eq + Hash, - S: BuildHasher + Default, - { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: Deserializer<'de>, - { - struct SeqVisitor<T, S> { - marker: PhantomData<HashSet<T, S>>, - } - - impl<'de, T, S> Visitor<'de> for SeqVisitor<T, S> - where - T: Deserialize<'de> + Eq + Hash, - S: BuildHasher + Default, - { - type Value = HashSet<T, S>; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a sequence") - } - - #[cfg_attr(feature = "inline-more", inline)] - fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> - where - A: SeqAccess<'de>, - { - let mut values = HashSet::with_capacity_and_hasher( - size_hint::cautious(seq.size_hint()), - S::default(), - ); - - while let Some(value) = seq.next_element()? { - values.insert(value); - } - - Ok(values) - } - } - - let visitor = SeqVisitor { - marker: PhantomData, - }; - deserializer.deserialize_seq(visitor) - } - - #[allow(clippy::missing_errors_doc)] - fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error> - where - D: Deserializer<'de>, - { - struct SeqInPlaceVisitor<'a, T, S>(&'a mut HashSet<T, S>); - - impl<'a, 'de, T, S> Visitor<'de> for SeqInPlaceVisitor<'a, T, S> - where - T: Deserialize<'de> + Eq + Hash, - S: BuildHasher + Default, - { - type Value = (); - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a sequence") - } - - #[cfg_attr(feature = "inline-more", inline)] - fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> - where - A: SeqAccess<'de>, - { - self.0.clear(); - self.0.reserve(size_hint::cautious(seq.size_hint())); - - while let Some(value) = seq.next_element()? { - self.0.insert(value); - } - - Ok(()) - } - } - - deserializer.deserialize_seq(SeqInPlaceVisitor(place)) - } - } -} diff --git a/vendor/hashbrown-0.13.2/src/lib.rs b/vendor/hashbrown-0.13.2/src/lib.rs deleted file mode 100644 index e43165dd6..000000000 --- a/vendor/hashbrown-0.13.2/src/lib.rs +++ /dev/null @@ -1,183 +0,0 @@ -//! This crate is a Rust port of Google's high-performance [SwissTable] hash -//! map, adapted to make it a drop-in replacement for Rust's standard `HashMap` -//! and `HashSet` types. -//! -//! The original C++ version of [SwissTable] can be found [here], and this -//! [CppCon talk] gives an overview of how the algorithm works. -//! -//! [SwissTable]: https://abseil.io/blog/20180927-swisstables -//! [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h -//! [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4 - -#![no_std] -#![cfg_attr( - feature = "nightly", - feature( - test, - core_intrinsics, - dropck_eyepatch, - min_specialization, - extend_one, - allocator_api, - slice_ptr_get, - nonnull_slice_from_raw_parts, - maybe_uninit_array_assume_init, - build_hasher_simple_hash_one - ) -)] -#![allow( - clippy::doc_markdown, - clippy::module_name_repetitions, - clippy::must_use_candidate, - clippy::option_if_let_else, - clippy::redundant_else, - clippy::manual_map, - clippy::missing_safety_doc, - clippy::missing_errors_doc -)] -#![warn(missing_docs)] -#![warn(rust_2018_idioms)] - -#[cfg(test)] -#[macro_use] -extern crate std; - -#[cfg_attr(test, macro_use)] -extern crate alloc; - -#[cfg(feature = "nightly")] -#[cfg(doctest)] -doc_comment::doctest!("../README.md"); - -#[macro_use] -mod macros; - -#[cfg(feature = "raw")] -/// Experimental and unsafe `RawTable` API. This module is only available if the -/// `raw` feature is enabled. -pub mod raw { - // The RawTable API is still experimental and is not properly documented yet. - #[allow(missing_docs)] - #[path = "mod.rs"] - mod inner; - pub use inner::*; - - #[cfg(feature = "rayon")] - /// [rayon]-based parallel iterator types for hash maps. - /// You will rarely need to interact with it directly unless you have need - /// to name one of the iterator types. - /// - /// [rayon]: https://docs.rs/rayon/1.0/rayon - pub mod rayon { - pub use crate::external_trait_impls::rayon::raw::*; - } -} -#[cfg(not(feature = "raw"))] -mod raw; - -mod external_trait_impls; -mod map; -#[cfg(feature = "rustc-internal-api")] -mod rustc_entry; -mod scopeguard; -mod set; - -pub mod hash_map { - //! A hash map implemented with quadratic probing and SIMD lookup. - pub use crate::map::*; - - #[cfg(feature = "rustc-internal-api")] - pub use crate::rustc_entry::*; - - #[cfg(feature = "rayon")] - /// [rayon]-based parallel iterator types for hash maps. - /// You will rarely need to interact with it directly unless you have need - /// to name one of the iterator types. - /// - /// [rayon]: https://docs.rs/rayon/1.0/rayon - pub mod rayon { - pub use crate::external_trait_impls::rayon::map::*; - } -} -pub mod hash_set { - //! A hash set implemented as a `HashMap` where the value is `()`. - pub use crate::set::*; - - #[cfg(feature = "rayon")] - /// [rayon]-based parallel iterator types for hash sets. - /// You will rarely need to interact with it directly unless you have need - /// to name one of the iterator types. - /// - /// [rayon]: https://docs.rs/rayon/1.0/rayon - pub mod rayon { - pub use crate::external_trait_impls::rayon::set::*; - } -} - -pub use crate::map::HashMap; -pub use crate::set::HashSet; - -/// Key equivalence trait. -/// -/// This trait defines the function used to compare the input value with the -/// map keys (or set values) during a lookup operation such as [`HashMap::get`] -/// or [`HashSet::contains`]. -/// It is provided with a blanket implementation based on the -/// [`Borrow`](core::borrow::Borrow) trait. -/// -/// # Correctness -/// -/// Equivalent values must hash to the same value. -pub trait Equivalent<K: ?Sized> { - /// Checks if this value is equivalent to the given key. - /// - /// Returns `true` if both values are equivalent, and `false` otherwise. - /// - /// # Correctness - /// - /// When this function returns `true`, both `self` and `key` must hash to - /// the same value. - fn equivalent(&self, key: &K) -> bool; -} - -impl<Q: ?Sized, K: ?Sized> Equivalent<K> for Q -where - Q: Eq, - K: core::borrow::Borrow<Q>, -{ - fn equivalent(&self, key: &K) -> bool { - self == key.borrow() - } -} - -/// The error type for `try_reserve` methods. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum TryReserveError { - /// Error due to the computed capacity exceeding the collection's maximum - /// (usually `isize::MAX` bytes). - CapacityOverflow, - - /// The memory allocator returned an error - AllocError { - /// The layout of the allocation request that failed. - layout: alloc::alloc::Layout, - }, -} - -/// Wrapper around `Bump` which allows it to be used as an allocator for -/// `HashMap`, `HashSet` and `RawTable`. -/// -/// `Bump` can be used directly without this wrapper on nightly if you enable -/// the `allocator-api` feature of the `bumpalo` crate. -#[cfg(feature = "bumpalo")] -#[derive(Clone, Copy, Debug)] -pub struct BumpWrapper<'a>(pub &'a bumpalo::Bump); - -#[cfg(feature = "bumpalo")] -#[test] -fn test_bumpalo() { - use bumpalo::Bump; - let bump = Bump::new(); - let mut map = HashMap::new_in(BumpWrapper(&bump)); - map.insert(0, 1); -} diff --git a/vendor/hashbrown-0.13.2/src/macros.rs b/vendor/hashbrown-0.13.2/src/macros.rs deleted file mode 100644 index f8ef917b1..000000000 --- a/vendor/hashbrown-0.13.2/src/macros.rs +++ /dev/null @@ -1,70 +0,0 @@ -// See the cfg-if crate. -#[allow(unused_macro_rules)] -macro_rules! cfg_if { - // match if/else chains with a final `else` - ($( - if #[cfg($($meta:meta),*)] { $($it:item)* } - ) else * else { - $($it2:item)* - }) => { - cfg_if! { - @__items - () ; - $( ( ($($meta),*) ($($it)*) ), )* - ( () ($($it2)*) ), - } - }; - - // match if/else chains lacking a final `else` - ( - if #[cfg($($i_met:meta),*)] { $($i_it:item)* } - $( - else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } - )* - ) => { - cfg_if! { - @__items - () ; - ( ($($i_met),*) ($($i_it)*) ), - $( ( ($($e_met),*) ($($e_it)*) ), )* - ( () () ), - } - }; - - // Internal and recursive macro to emit all the items - // - // Collects all the negated cfgs in a list at the beginning and after the - // semicolon is all the remaining items - (@__items ($($not:meta,)*) ; ) => {}; - (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { - // Emit all items within one block, applying an approprate #[cfg]. The - // #[cfg] will require all `$m` matchers specified and must also negate - // all previous matchers. - cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } - - // Recurse to emit all other items in `$rest`, and when we do so add all - // our `$m` matchers to the list of `$not` matchers as future emissions - // will have to negate everything we just matched as well. - cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } - }; - - // Internal macro to Apply a cfg attribute to a list of items - (@__apply $m:meta, $($it:item)*) => { - $(#[$m] $it)* - }; -} - -// Helper macro for specialization. This also helps avoid parse errors if the -// default fn syntax for specialization changes in the future. -#[cfg(feature = "nightly")] -macro_rules! default_fn { - (#[$($a:tt)*] $($tt:tt)*) => { - #[$($a)*] default $($tt)* - } -} -#[cfg(not(feature = "nightly"))] -macro_rules! default_fn { - ($($tt:tt)*) => { - $($tt)* - } -} diff --git a/vendor/hashbrown-0.13.2/src/map.rs b/vendor/hashbrown-0.13.2/src/map.rs deleted file mode 100644 index e238bf66b..000000000 --- a/vendor/hashbrown-0.13.2/src/map.rs +++ /dev/null @@ -1,8512 +0,0 @@ -use crate::raw::{Allocator, Bucket, Global, RawDrain, RawIntoIter, RawIter, RawTable}; -use crate::{Equivalent, TryReserveError}; -use core::borrow::Borrow; -use core::fmt::{self, Debug}; -use core::hash::{BuildHasher, Hash}; -use core::iter::{FromIterator, FusedIterator}; -use core::marker::PhantomData; -use core::mem; -use core::ops::Index; - -/// Default hasher for `HashMap`. -#[cfg(feature = "ahash")] -pub type DefaultHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>; - -/// Dummy default hasher for `HashMap`. -#[cfg(not(feature = "ahash"))] -pub enum DefaultHashBuilder {} - -/// A hash map implemented with quadratic probing and SIMD lookup. -/// -/// The default hashing algorithm is currently [`AHash`], though this is -/// subject to change at any point in the future. This hash function is very -/// fast for all types of keys, but this algorithm will typically *not* protect -/// against attacks such as HashDoS. -/// -/// The hashing algorithm can be replaced on a per-`HashMap` basis using the -/// [`default`], [`with_hasher`], and [`with_capacity_and_hasher`] methods. Many -/// alternative algorithms are available on crates.io, such as the [`fnv`] crate. -/// -/// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although -/// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`. -/// If you implement these yourself, it is important that the following -/// property holds: -/// -/// ```text -/// k1 == k2 -> hash(k1) == hash(k2) -/// ``` -/// -/// In other words, if two keys are equal, their hashes must be equal. -/// -/// It is a logic error for a key to be modified in such a way that the key's -/// hash, as determined by the [`Hash`] trait, or its equality, as determined by -/// the [`Eq`] trait, changes while it is in the map. This is normally only -/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. -/// -/// It is also a logic error for the [`Hash`] implementation of a key to panic. -/// This is generally only possible if the trait is implemented manually. If a -/// panic does occur then the contents of the `HashMap` may become corrupted and -/// some items may be dropped from the table. -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// // Type inference lets us omit an explicit type signature (which -/// // would be `HashMap<String, String>` in this example). -/// let mut book_reviews = HashMap::new(); -/// -/// // Review some books. -/// book_reviews.insert( -/// "Adventures of Huckleberry Finn".to_string(), -/// "My favorite book.".to_string(), -/// ); -/// book_reviews.insert( -/// "Grimms' Fairy Tales".to_string(), -/// "Masterpiece.".to_string(), -/// ); -/// book_reviews.insert( -/// "Pride and Prejudice".to_string(), -/// "Very enjoyable.".to_string(), -/// ); -/// book_reviews.insert( -/// "The Adventures of Sherlock Holmes".to_string(), -/// "Eye lyked it alot.".to_string(), -/// ); -/// -/// // Check for a specific one. -/// // When collections store owned values (String), they can still be -/// // queried using references (&str). -/// if !book_reviews.contains_key("Les Misérables") { -/// println!("We've got {} reviews, but Les Misérables ain't one.", -/// book_reviews.len()); -/// } -/// -/// // oops, this review has a lot of spelling mistakes, let's delete it. -/// book_reviews.remove("The Adventures of Sherlock Holmes"); -/// -/// // Look up the values associated with some keys. -/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"]; -/// for &book in &to_find { -/// match book_reviews.get(book) { -/// Some(review) => println!("{}: {}", book, review), -/// None => println!("{} is unreviewed.", book) -/// } -/// } -/// -/// // Look up the value for a key (will panic if the key is not found). -/// println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]); -/// -/// // Iterate over everything. -/// for (book, review) in &book_reviews { -/// println!("{}: \"{}\"", book, review); -/// } -/// ``` -/// -/// `HashMap` also implements an [`Entry API`](#method.entry), which allows -/// for more complex methods of getting, setting, updating and removing keys and -/// their values: -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// // type inference lets us omit an explicit type signature (which -/// // would be `HashMap<&str, u8>` in this example). -/// let mut player_stats = HashMap::new(); -/// -/// fn random_stat_buff() -> u8 { -/// // could actually return some random value here - let's just return -/// // some fixed value for now -/// 42 -/// } -/// -/// // insert a key only if it doesn't already exist -/// player_stats.entry("health").or_insert(100); -/// -/// // insert a key using a function that provides a new value only if it -/// // doesn't already exist -/// player_stats.entry("defence").or_insert_with(random_stat_buff); -/// -/// // update a key, guarding against the key possibly not being set -/// let stat = player_stats.entry("attack").or_insert(100); -/// *stat += random_stat_buff(); -/// ``` -/// -/// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`]. -/// We must also derive [`PartialEq`]. -/// -/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html -/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html -/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html -/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html -/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html -/// [`default`]: #method.default -/// [`with_hasher`]: #method.with_hasher -/// [`with_capacity_and_hasher`]: #method.with_capacity_and_hasher -/// [`fnv`]: https://crates.io/crates/fnv -/// [`AHash`]: https://crates.io/crates/ahash -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// #[derive(Hash, Eq, PartialEq, Debug)] -/// struct Viking { -/// name: String, -/// country: String, -/// } -/// -/// impl Viking { -/// /// Creates a new Viking. -/// fn new(name: &str, country: &str) -> Viking { -/// Viking { name: name.to_string(), country: country.to_string() } -/// } -/// } -/// -/// // Use a HashMap to store the vikings' health points. -/// let mut vikings = HashMap::new(); -/// -/// vikings.insert(Viking::new("Einar", "Norway"), 25); -/// vikings.insert(Viking::new("Olaf", "Denmark"), 24); -/// vikings.insert(Viking::new("Harald", "Iceland"), 12); -/// -/// // Use derived implementation to print the status of the vikings. -/// for (viking, health) in &vikings { -/// println!("{:?} has {} hp", viking, health); -/// } -/// ``` -/// -/// A `HashMap` with fixed list of elements can be initialized from an array: -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let timber_resources: HashMap<&str, i32> = [("Norway", 100), ("Denmark", 50), ("Iceland", 10)] -/// .iter().cloned().collect(); -/// // use the values stored in map -/// ``` -pub struct HashMap<K, V, S = DefaultHashBuilder, A: Allocator + Clone = Global> { - pub(crate) hash_builder: S, - pub(crate) table: RawTable<(K, V), A>, -} - -impl<K: Clone, V: Clone, S: Clone, A: Allocator + Clone> Clone for HashMap<K, V, S, A> { - fn clone(&self) -> Self { - HashMap { - hash_builder: self.hash_builder.clone(), - table: self.table.clone(), - } - } - - fn clone_from(&mut self, source: &Self) { - self.table.clone_from(&source.table); - - // Update hash_builder only if we successfully cloned all elements. - self.hash_builder.clone_from(&source.hash_builder); - } -} - -/// Ensures that a single closure type across uses of this which, in turn prevents multiple -/// instances of any functions like RawTable::reserve from being generated -#[cfg_attr(feature = "inline-more", inline)] -pub(crate) fn make_hasher<Q, V, S>(hash_builder: &S) -> impl Fn(&(Q, V)) -> u64 + '_ -where - Q: Hash, - S: BuildHasher, -{ - move |val| make_hash::<Q, S>(hash_builder, &val.0) -} - -/// Ensures that a single closure type across uses of this which, in turn prevents multiple -/// instances of any functions like RawTable::reserve from being generated -#[cfg_attr(feature = "inline-more", inline)] -fn equivalent_key<Q, K, V>(k: &Q) -> impl Fn(&(K, V)) -> bool + '_ -where - Q: ?Sized + Equivalent<K>, -{ - move |x| k.equivalent(&x.0) -} - -/// Ensures that a single closure type across uses of this which, in turn prevents multiple -/// instances of any functions like RawTable::reserve from being generated -#[cfg_attr(feature = "inline-more", inline)] -fn equivalent<Q, K>(k: &Q) -> impl Fn(&K) -> bool + '_ -where - Q: ?Sized + Equivalent<K>, -{ - move |x| k.equivalent(x) -} - -#[cfg(not(feature = "nightly"))] -#[cfg_attr(feature = "inline-more", inline)] -pub(crate) fn make_hash<Q, S>(hash_builder: &S, val: &Q) -> u64 -where - Q: Hash + ?Sized, - S: BuildHasher, -{ - use core::hash::Hasher; - let mut state = hash_builder.build_hasher(); - val.hash(&mut state); - state.finish() -} - -#[cfg(feature = "nightly")] -#[cfg_attr(feature = "inline-more", inline)] -pub(crate) fn make_hash<Q, S>(hash_builder: &S, val: &Q) -> u64 -where - Q: Hash + ?Sized, - S: BuildHasher, -{ - hash_builder.hash_one(val) -} - -#[cfg(not(feature = "nightly"))] -#[cfg_attr(feature = "inline-more", inline)] -pub(crate) fn make_insert_hash<K, S>(hash_builder: &S, val: &K) -> u64 -where - K: Hash, - S: BuildHasher, -{ - use core::hash::Hasher; - let mut state = hash_builder.build_hasher(); - val.hash(&mut state); - state.finish() -} - -#[cfg(feature = "nightly")] -#[cfg_attr(feature = "inline-more", inline)] -pub(crate) fn make_insert_hash<K, S>(hash_builder: &S, val: &K) -> u64 -where - K: Hash, - S: BuildHasher, -{ - hash_builder.hash_one(val) -} - -#[cfg(feature = "ahash")] -impl<K, V> HashMap<K, V, DefaultHashBuilder> { - /// Creates an empty `HashMap`. - /// - /// The hash map is initially created with a capacity of 0, so it will not allocate until it - /// is first inserted into. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashMap`], for example with - /// [`with_hasher`](HashMap::with_hasher) method. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let mut map: HashMap<&str, i32> = HashMap::new(); - /// assert_eq!(map.len(), 0); - /// assert_eq!(map.capacity(), 0); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn new() -> Self { - Self::default() - } - - /// Creates an empty `HashMap` with the specified capacity. - /// - /// The hash map will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash map will not allocate. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashMap`], for example with - /// [`with_capacity_and_hasher`](HashMap::with_capacity_and_hasher) method. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10); - /// assert_eq!(map.len(), 0); - /// assert!(map.capacity() >= 10); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_and_hasher(capacity, DefaultHashBuilder::default()) - } -} - -#[cfg(feature = "ahash")] -impl<K, V, A: Allocator + Clone> HashMap<K, V, DefaultHashBuilder, A> { - /// Creates an empty `HashMap` using the given allocator. - /// - /// The hash map is initially created with a capacity of 0, so it will not allocate until it - /// is first inserted into. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashMap`], for example with - /// [`with_hasher_in`](HashMap::with_hasher_in) method. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// # #[cfg(feature = "bumpalo")] - /// # fn test() { - /// use hashbrown::{HashMap, BumpWrapper}; - /// use bumpalo::Bump; - /// - /// let bump = Bump::new(); - /// let mut map = HashMap::new_in(BumpWrapper(&bump)); - /// - /// // The created HashMap holds none elements - /// assert_eq!(map.len(), 0); - /// - /// // The created HashMap also doesn't allocate memory - /// assert_eq!(map.capacity(), 0); - /// - /// // Now we insert element inside created HashMap - /// map.insert("One", 1); - /// // We can see that the HashMap holds 1 element - /// assert_eq!(map.len(), 1); - /// // And it also allocates some capacity - /// assert!(map.capacity() > 1); - /// # } - /// # fn main() { - /// # #[cfg(feature = "bumpalo")] - /// # test() - /// # } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn new_in(alloc: A) -> Self { - Self::with_hasher_in(DefaultHashBuilder::default(), alloc) - } - - /// Creates an empty `HashMap` with the specified capacity using the given allocator. - /// - /// The hash map will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash map will not allocate. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashMap`], for example with - /// [`with_capacity_and_hasher_in`](HashMap::with_capacity_and_hasher_in) method. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// # #[cfg(feature = "bumpalo")] - /// # fn test() { - /// use hashbrown::{HashMap, BumpWrapper}; - /// use bumpalo::Bump; - /// - /// let bump = Bump::new(); - /// let mut map = HashMap::with_capacity_in(5, BumpWrapper(&bump)); - /// - /// // The created HashMap holds none elements - /// assert_eq!(map.len(), 0); - /// // But it can hold at least 5 elements without reallocating - /// let empty_map_capacity = map.capacity(); - /// assert!(empty_map_capacity >= 5); - /// - /// // Now we insert some 5 elements inside created HashMap - /// map.insert("One", 1); - /// map.insert("Two", 2); - /// map.insert("Three", 3); - /// map.insert("Four", 4); - /// map.insert("Five", 5); - /// - /// // We can see that the HashMap holds 5 elements - /// assert_eq!(map.len(), 5); - /// // But its capacity isn't changed - /// assert_eq!(map.capacity(), empty_map_capacity) - /// # } - /// # fn main() { - /// # #[cfg(feature = "bumpalo")] - /// # test() - /// # } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - Self::with_capacity_and_hasher_in(capacity, DefaultHashBuilder::default(), alloc) - } -} - -impl<K, V, S> HashMap<K, V, S> { - /// Creates an empty `HashMap` which will use the given hash builder to hash - /// keys. - /// - /// The hash map is initially created with a capacity of 0, so it will not - /// allocate until it is first inserted into. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashMap`]. - /// - /// The `hash_builder` passed should implement the [`BuildHasher`] trait for - /// the HashMap to be useful, see its documentation for details. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut map = HashMap::with_hasher(s); - /// assert_eq!(map.len(), 0); - /// assert_eq!(map.capacity(), 0); - /// - /// map.insert(1, 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub const fn with_hasher(hash_builder: S) -> Self { - Self { - hash_builder, - table: RawTable::new(), - } - } - - /// Creates an empty `HashMap` with the specified capacity, using `hash_builder` - /// to hash the keys. - /// - /// The hash map will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash map will not allocate. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashMap`]. - /// - /// The `hash_builder` passed should implement the [`BuildHasher`] trait for - /// the HashMap to be useful, see its documentation for details. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut map = HashMap::with_capacity_and_hasher(10, s); - /// assert_eq!(map.len(), 0); - /// assert!(map.capacity() >= 10); - /// - /// map.insert(1, 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { - Self { - hash_builder, - table: RawTable::with_capacity(capacity), - } - } -} - -impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> { - /// Returns a reference to the underlying allocator. - #[inline] - pub fn allocator(&self) -> &A { - self.table.allocator() - } - - /// Creates an empty `HashMap` which will use the given hash builder to hash - /// keys. It will be allocated with the given allocator. - /// - /// The hash map is initially created with a capacity of 0, so it will not allocate until it - /// is first inserted into. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashMap`]. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut map = HashMap::with_hasher(s); - /// map.insert(1, 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub const fn with_hasher_in(hash_builder: S, alloc: A) -> Self { - Self { - hash_builder, - table: RawTable::new_in(alloc), - } - } - - /// Creates an empty `HashMap` with the specified capacity, using `hash_builder` - /// to hash the keys. It will be allocated with the given allocator. - /// - /// The hash map will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash map will not allocate. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashMap` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashMap`]. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut map = HashMap::with_capacity_and_hasher(10, s); - /// map.insert(1, 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn with_capacity_and_hasher_in(capacity: usize, hash_builder: S, alloc: A) -> Self { - Self { - hash_builder, - table: RawTable::with_capacity_in(capacity, alloc), - } - } - - /// Returns a reference to the map's [`BuildHasher`]. - /// - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let hasher = DefaultHashBuilder::default(); - /// let map: HashMap<i32, i32> = HashMap::with_hasher(hasher); - /// let hasher: &DefaultHashBuilder = map.hasher(); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn hasher(&self) -> &S { - &self.hash_builder - } - - /// Returns the number of elements the map can hold without reallocating. - /// - /// This number is a lower bound; the `HashMap<K, V>` might be able to hold - /// more, but is guaranteed to be able to hold at least this many. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let map: HashMap<i32, i32> = HashMap::with_capacity(100); - /// assert_eq!(map.len(), 0); - /// assert!(map.capacity() >= 100); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn capacity(&self) -> usize { - self.table.capacity() - } - - /// An iterator visiting all keys in arbitrary order. - /// The iterator element type is `&'a K`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// assert_eq!(map.len(), 3); - /// let mut vec: Vec<&str> = Vec::new(); - /// - /// for key in map.keys() { - /// println!("{}", key); - /// vec.push(*key); - /// } - /// - /// // The `Keys` iterator produces keys in arbitrary order, so the - /// // keys must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, ["a", "b", "c"]); - /// - /// assert_eq!(map.len(), 3); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn keys(&self) -> Keys<'_, K, V> { - Keys { inner: self.iter() } - } - - /// An iterator visiting all values in arbitrary order. - /// The iterator element type is `&'a V`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// assert_eq!(map.len(), 3); - /// let mut vec: Vec<i32> = Vec::new(); - /// - /// for val in map.values() { - /// println!("{}", val); - /// vec.push(*val); - /// } - /// - /// // The `Values` iterator produces values in arbitrary order, so the - /// // values must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [1, 2, 3]); - /// - /// assert_eq!(map.len(), 3); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn values(&self) -> Values<'_, K, V> { - Values { inner: self.iter() } - } - - /// An iterator visiting all values mutably in arbitrary order. - /// The iterator element type is `&'a mut V`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for val in map.values_mut() { - /// *val = *val + 10; - /// } - /// - /// assert_eq!(map.len(), 3); - /// let mut vec: Vec<i32> = Vec::new(); - /// - /// for val in map.values() { - /// println!("{}", val); - /// vec.push(*val); - /// } - /// - /// // The `Values` iterator produces values in arbitrary order, so the - /// // values must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [11, 12, 13]); - /// - /// assert_eq!(map.len(), 3); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { - ValuesMut { - inner: self.iter_mut(), - } - } - - /// An iterator visiting all key-value pairs in arbitrary order. - /// The iterator element type is `(&'a K, &'a V)`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// assert_eq!(map.len(), 3); - /// let mut vec: Vec<(&str, i32)> = Vec::new(); - /// - /// for (key, val) in map.iter() { - /// println!("key: {} val: {}", key, val); - /// vec.push((*key, *val)); - /// } - /// - /// // The `Iter` iterator produces items in arbitrary order, so the - /// // items must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [("a", 1), ("b", 2), ("c", 3)]); - /// - /// assert_eq!(map.len(), 3); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn iter(&self) -> Iter<'_, K, V> { - // Here we tie the lifetime of self to the iter. - unsafe { - Iter { - inner: self.table.iter(), - marker: PhantomData, - } - } - } - - /// An iterator visiting all key-value pairs in arbitrary order, - /// with mutable references to the values. - /// The iterator element type is `(&'a K, &'a mut V)`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Update all values - /// for (_, val) in map.iter_mut() { - /// *val *= 2; - /// } - /// - /// assert_eq!(map.len(), 3); - /// let mut vec: Vec<(&str, i32)> = Vec::new(); - /// - /// for (key, val) in &map { - /// println!("key: {} val: {}", key, val); - /// vec.push((*key, *val)); - /// } - /// - /// // The `Iter` iterator produces items in arbitrary order, so the - /// // items must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [("a", 2), ("b", 4), ("c", 6)]); - /// - /// assert_eq!(map.len(), 3); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { - // Here we tie the lifetime of self to the iter. - unsafe { - IterMut { - inner: self.table.iter(), - marker: PhantomData, - } - } - } - - #[cfg(test)] - #[cfg_attr(feature = "inline-more", inline)] - fn raw_capacity(&self) -> usize { - self.table.buckets() - } - - /// Returns the number of elements in the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert_eq!(a.len(), 0); - /// a.insert(1, "a"); - /// assert_eq!(a.len(), 1); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn len(&self) -> usize { - self.table.len() - } - - /// Returns `true` if the map contains no elements. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert!(a.is_empty()); - /// a.insert(1, "a"); - /// assert!(!a.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Clears the map, returning all key-value pairs as an iterator. Keeps the - /// allocated memory for reuse. - /// - /// If the returned iterator is dropped before being fully consumed, it - /// drops the remaining key-value pairs. The returned iterator keeps a - /// mutable borrow on the vector to optimize its implementation. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// let capacity_before_drain = a.capacity(); - /// - /// for (k, v) in a.drain().take(1) { - /// assert!(k == 1 || k == 2); - /// assert!(v == "a" || v == "b"); - /// } - /// - /// // As we can see, the map is empty and contains no element. - /// assert!(a.is_empty() && a.len() == 0); - /// // But map capacity is equal to old one. - /// assert_eq!(a.capacity(), capacity_before_drain); - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// - /// { // Iterator is dropped without being consumed. - /// let d = a.drain(); - /// } - /// - /// // But the map is empty even if we do not use Drain iterator. - /// assert!(a.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn drain(&mut self) -> Drain<'_, K, V, A> { - Drain { - inner: self.table.drain(), - } - } - - /// Retains only the elements specified by the predicate. Keeps the - /// allocated memory for reuse. - /// - /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. - /// The elements are visited in unsorted (and unspecified) order. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect(); - /// assert_eq!(map.len(), 8); - /// - /// map.retain(|&k, _| k % 2 == 0); - /// - /// // We can see, that the number of elements inside map is changed. - /// assert_eq!(map.len(), 4); - /// - /// let mut vec: Vec<(i32, i32)> = map.iter().map(|(&k, &v)| (k, v)).collect(); - /// vec.sort_unstable(); - /// assert_eq!(vec, [(0, 0), (2, 20), (4, 40), (6, 60)]); - /// ``` - pub fn retain<F>(&mut self, mut f: F) - where - F: FnMut(&K, &mut V) -> bool, - { - // Here we only use `iter` as a temporary, preventing use-after-free - unsafe { - for item in self.table.iter() { - let &mut (ref key, ref mut value) = item.as_mut(); - if !f(key, value) { - self.table.erase(item); - } - } - } - } - - /// Drains elements which are true under the given predicate, - /// and returns an iterator over the removed items. - /// - /// In other words, move all pairs `(k, v)` such that `f(&k, &mut v)` returns `true` out - /// into another iterator. - /// - /// Note that `drain_filter` lets you mutate every value in the filter closure, regardless of - /// whether you choose to keep or remove it. - /// - /// When the returned DrainedFilter is dropped, any remaining elements that satisfy - /// the predicate are dropped from the table. - /// - /// It is unspecified how many more elements will be subjected to the closure - /// if a panic occurs in the closure, or a panic occurs while dropping an element, - /// or if the `DrainFilter` value is leaked. - /// - /// Keeps the allocated memory for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect(); - /// - /// let drained: HashMap<i32, i32> = map.drain_filter(|k, _v| k % 2 == 0).collect(); - /// - /// let mut evens = drained.keys().cloned().collect::<Vec<_>>(); - /// let mut odds = map.keys().cloned().collect::<Vec<_>>(); - /// evens.sort(); - /// odds.sort(); - /// - /// assert_eq!(evens, vec![0, 2, 4, 6]); - /// assert_eq!(odds, vec![1, 3, 5, 7]); - /// - /// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect(); - /// - /// { // Iterator is dropped without being consumed. - /// let d = map.drain_filter(|k, _v| k % 2 != 0); - /// } - /// - /// // But the map lens have been reduced by half - /// // even if we do not use DrainFilter iterator. - /// assert_eq!(map.len(), 4); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F, A> - where - F: FnMut(&K, &mut V) -> bool, - { - DrainFilter { - f, - inner: DrainFilterInner { - iter: unsafe { self.table.iter() }, - table: &mut self.table, - }, - } - } - - /// Clears the map, removing all key-value pairs. Keeps the allocated memory - /// for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// let capacity_before_clear = a.capacity(); - /// - /// a.clear(); - /// - /// // Map is empty. - /// assert!(a.is_empty()); - /// // But map capacity is equal to old one. - /// assert_eq!(a.capacity(), capacity_before_clear); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn clear(&mut self) { - self.table.clear(); - } - - /// Creates a consuming iterator visiting all the keys in arbitrary order. - /// The map cannot be used after calling this. - /// The iterator element type is `K`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// let mut vec: Vec<&str> = map.into_keys().collect(); - /// - /// // The `IntoKeys` iterator produces keys in arbitrary order, so the - /// // keys must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, ["a", "b", "c"]); - /// ``` - #[inline] - pub fn into_keys(self) -> IntoKeys<K, V, A> { - IntoKeys { - inner: self.into_iter(), - } - } - - /// Creates a consuming iterator visiting all the values in arbitrary order. - /// The map cannot be used after calling this. - /// The iterator element type is `V`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// let mut vec: Vec<i32> = map.into_values().collect(); - /// - /// // The `IntoValues` iterator produces values in arbitrary order, so - /// // the values must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [1, 2, 3]); - /// ``` - #[inline] - pub fn into_values(self) -> IntoValues<K, V, A> { - IntoValues { - inner: self.into_iter(), - } - } -} - -impl<K, V, S, A> HashMap<K, V, S, A> -where - K: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `HashMap`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Panics - /// - /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`] the program - /// in case of allocation error. Use [`try_reserve`](HashMap::try_reserve) instead - /// if you want to handle memory allocation failure. - /// - /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html - /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let mut map: HashMap<&str, i32> = HashMap::new(); - /// // Map is empty and doesn't allocate memory - /// assert_eq!(map.capacity(), 0); - /// - /// map.reserve(10); - /// - /// // And now map can hold at least 10 elements - /// assert!(map.capacity() >= 10); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn reserve(&mut self, additional: usize) { - self.table - .reserve(additional, make_hasher::<_, V, S>(&self.hash_builder)); - } - - /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `HashMap<K,V>`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, isize> = HashMap::new(); - /// // Map is empty and doesn't allocate memory - /// assert_eq!(map.capacity(), 0); - /// - /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); - /// - /// // And now map can hold at least 10 elements - /// assert!(map.capacity() >= 10); - /// ``` - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned: - /// ``` - /// # fn test() { - /// use hashbrown::HashMap; - /// use hashbrown::TryReserveError; - /// let mut map: HashMap<i32, i32> = HashMap::new(); - /// - /// match map.try_reserve(usize::MAX) { - /// Err(error) => match error { - /// TryReserveError::CapacityOverflow => {} - /// _ => panic!("TryReserveError::AllocError ?"), - /// }, - /// _ => panic!(), - /// } - /// # } - /// # fn main() { - /// # #[cfg(not(miri))] - /// # test() - /// # } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.table - .try_reserve(additional, make_hasher::<_, V, S>(&self.hash_builder)) - } - - /// Shrinks the capacity of the map as much as possible. It will drop - /// down as much as possible while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100); - /// map.insert(1, 2); - /// map.insert(3, 4); - /// assert!(map.capacity() >= 100); - /// map.shrink_to_fit(); - /// assert!(map.capacity() >= 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn shrink_to_fit(&mut self) { - self.table - .shrink_to(0, make_hasher::<_, V, S>(&self.hash_builder)); - } - - /// Shrinks the capacity of the map with a lower limit. It will drop - /// down no lower than the supplied limit while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// This function does nothing if the current capacity is smaller than the - /// supplied minimum capacity. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100); - /// map.insert(1, 2); - /// map.insert(3, 4); - /// assert!(map.capacity() >= 100); - /// map.shrink_to(10); - /// assert!(map.capacity() >= 10); - /// map.shrink_to(0); - /// assert!(map.capacity() >= 2); - /// map.shrink_to(10); - /// assert!(map.capacity() >= 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.table - .shrink_to(min_capacity, make_hasher::<_, V, S>(&self.hash_builder)); - } - - /// Gets the given key's corresponding entry in the map for in-place manipulation. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut letters = HashMap::new(); - /// - /// for ch in "a short treatise on fungi".chars() { - /// let counter = letters.entry(ch).or_insert(0); - /// *counter += 1; - /// } - /// - /// assert_eq!(letters[&'s'], 2); - /// assert_eq!(letters[&'t'], 3); - /// assert_eq!(letters[&'u'], 1); - /// assert_eq!(letters.get(&'y'), None); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S, A> { - let hash = make_insert_hash::<K, S>(&self.hash_builder, &key); - if let Some(elem) = self.table.find(hash, equivalent_key(&key)) { - Entry::Occupied(OccupiedEntry { - hash, - key: Some(key), - elem, - table: self, - }) - } else { - Entry::Vacant(VacantEntry { - hash, - key, - table: self, - }) - } - } - - /// Gets the given key's corresponding entry by reference in the map for in-place manipulation. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut words: HashMap<String, usize> = HashMap::new(); - /// let source = ["poneyland", "horseyland", "poneyland", "poneyland"]; - /// for (i, &s) in source.iter().enumerate() { - /// let counter = words.entry_ref(s).or_insert(0); - /// *counter += 1; - /// } - /// - /// assert_eq!(words["poneyland"], 3); - /// assert_eq!(words["horseyland"], 1); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn entry_ref<'a, 'b, Q: ?Sized>(&'a mut self, key: &'b Q) -> EntryRef<'a, 'b, K, Q, V, S, A> - where - Q: Hash + Equivalent<K>, - { - let hash = make_hash::<Q, S>(&self.hash_builder, key); - if let Some(elem) = self.table.find(hash, equivalent_key(key)) { - EntryRef::Occupied(OccupiedEntryRef { - hash, - key: Some(KeyOrRef::Borrowed(key)), - elem, - table: self, - }) - } else { - EntryRef::Vacant(VacantEntryRef { - hash, - key: KeyOrRef::Borrowed(key), - table: self, - }) - } - } - - /// Returns a reference to the value corresponding to the key. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.get(&1), Some(&"a")); - /// assert_eq!(map.get(&2), None); - /// ``` - #[inline] - pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> - where - Q: Hash + Equivalent<K>, - { - // Avoid `Option::map` because it bloats LLVM IR. - match self.get_inner(k) { - Some(&(_, ref v)) => Some(v), - None => None, - } - } - - /// Returns the key-value pair corresponding to the supplied key. - /// - /// The supplied key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); - /// assert_eq!(map.get_key_value(&2), None); - /// ``` - #[inline] - pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)> - where - Q: Hash + Equivalent<K>, - { - // Avoid `Option::map` because it bloats LLVM IR. - match self.get_inner(k) { - Some(&(ref key, ref value)) => Some((key, value)), - None => None, - } - } - - #[inline] - fn get_inner<Q: ?Sized>(&self, k: &Q) -> Option<&(K, V)> - where - Q: Hash + Equivalent<K>, - { - if self.table.is_empty() { - None - } else { - let hash = make_hash::<Q, S>(&self.hash_builder, k); - self.table.get(hash, equivalent_key(k)) - } - } - - /// Returns the key-value pair corresponding to the supplied key, with a mutable reference to value. - /// - /// The supplied key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// let (k, v) = map.get_key_value_mut(&1).unwrap(); - /// assert_eq!(k, &1); - /// assert_eq!(v, &mut "a"); - /// *v = "b"; - /// assert_eq!(map.get_key_value_mut(&1), Some((&1, &mut "b"))); - /// assert_eq!(map.get_key_value_mut(&2), None); - /// ``` - #[inline] - pub fn get_key_value_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<(&K, &mut V)> - where - Q: Hash + Equivalent<K>, - { - // Avoid `Option::map` because it bloats LLVM IR. - match self.get_inner_mut(k) { - Some(&mut (ref key, ref mut value)) => Some((key, value)), - None => None, - } - } - - /// Returns `true` if the map contains a value for the specified key. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.contains_key(&1), true); - /// assert_eq!(map.contains_key(&2), false); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool - where - Q: Hash + Equivalent<K>, - { - self.get_inner(k).is_some() - } - - /// Returns a mutable reference to the value corresponding to the key. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// if let Some(x) = map.get_mut(&1) { - /// *x = "b"; - /// } - /// assert_eq!(map[&1], "b"); - /// - /// assert_eq!(map.get_mut(&2), None); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> - where - Q: Hash + Equivalent<K>, - { - // Avoid `Option::map` because it bloats LLVM IR. - match self.get_inner_mut(k) { - Some(&mut (_, ref mut v)) => Some(v), - None => None, - } - } - - #[inline] - fn get_inner_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut (K, V)> - where - Q: Hash + Equivalent<K>, - { - if self.table.is_empty() { - None - } else { - let hash = make_hash::<Q, S>(&self.hash_builder, k); - self.table.get_mut(hash, equivalent_key(k)) - } - } - - /// Attempts to get mutable references to `N` values in the map at once. - /// - /// Returns an array of length `N` with the results of each query. For soundness, at most one - /// mutable reference will be returned to any value. `None` will be returned if any of the - /// keys are duplicates or missing. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut libraries = HashMap::new(); - /// libraries.insert("Bodleian Library".to_string(), 1602); - /// libraries.insert("Athenæum".to_string(), 1807); - /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); - /// libraries.insert("Library of Congress".to_string(), 1800); - /// - /// let got = libraries.get_many_mut([ - /// "Athenæum", - /// "Library of Congress", - /// ]); - /// assert_eq!( - /// got, - /// Some([ - /// &mut 1807, - /// &mut 1800, - /// ]), - /// ); - /// - /// // Missing keys result in None - /// let got = libraries.get_many_mut([ - /// "Athenæum", - /// "New York Public Library", - /// ]); - /// assert_eq!(got, None); - /// - /// // Duplicate keys result in None - /// let got = libraries.get_many_mut([ - /// "Athenæum", - /// "Athenæum", - /// ]); - /// assert_eq!(got, None); - /// ``` - pub fn get_many_mut<Q: ?Sized, const N: usize>(&mut self, ks: [&Q; N]) -> Option<[&'_ mut V; N]> - where - Q: Hash + Equivalent<K>, - { - self.get_many_mut_inner(ks).map(|res| res.map(|(_, v)| v)) - } - - /// Attempts to get mutable references to `N` values in the map at once, without validating that - /// the values are unique. - /// - /// Returns an array of length `N` with the results of each query. `None` will be returned if - /// any of the keys are missing. - /// - /// For a safe alternative see [`get_many_mut`](`HashMap::get_many_mut`). - /// - /// # Safety - /// - /// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting - /// references are not used. - /// - /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut libraries = HashMap::new(); - /// libraries.insert("Bodleian Library".to_string(), 1602); - /// libraries.insert("Athenæum".to_string(), 1807); - /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); - /// libraries.insert("Library of Congress".to_string(), 1800); - /// - /// let got = libraries.get_many_mut([ - /// "Athenæum", - /// "Library of Congress", - /// ]); - /// assert_eq!( - /// got, - /// Some([ - /// &mut 1807, - /// &mut 1800, - /// ]), - /// ); - /// - /// // Missing keys result in None - /// let got = libraries.get_many_mut([ - /// "Athenæum", - /// "New York Public Library", - /// ]); - /// assert_eq!(got, None); - /// ``` - pub unsafe fn get_many_unchecked_mut<Q: ?Sized, const N: usize>( - &mut self, - ks: [&Q; N], - ) -> Option<[&'_ mut V; N]> - where - Q: Hash + Equivalent<K>, - { - self.get_many_unchecked_mut_inner(ks) - .map(|res| res.map(|(_, v)| v)) - } - - /// Attempts to get mutable references to `N` values in the map at once, with immutable - /// references to the corresponding keys. - /// - /// Returns an array of length `N` with the results of each query. For soundness, at most one - /// mutable reference will be returned to any value. `None` will be returned if any of the keys - /// are duplicates or missing. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut libraries = HashMap::new(); - /// libraries.insert("Bodleian Library".to_string(), 1602); - /// libraries.insert("Athenæum".to_string(), 1807); - /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); - /// libraries.insert("Library of Congress".to_string(), 1800); - /// - /// let got = libraries.get_many_key_value_mut([ - /// "Bodleian Library", - /// "Herzogin-Anna-Amalia-Bibliothek", - /// ]); - /// assert_eq!( - /// got, - /// Some([ - /// (&"Bodleian Library".to_string(), &mut 1602), - /// (&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691), - /// ]), - /// ); - /// // Missing keys result in None - /// let got = libraries.get_many_key_value_mut([ - /// "Bodleian Library", - /// "Gewandhaus", - /// ]); - /// assert_eq!(got, None); - /// - /// // Duplicate keys result in None - /// let got = libraries.get_many_key_value_mut([ - /// "Bodleian Library", - /// "Herzogin-Anna-Amalia-Bibliothek", - /// "Herzogin-Anna-Amalia-Bibliothek", - /// ]); - /// assert_eq!(got, None); - /// ``` - pub fn get_many_key_value_mut<Q: ?Sized, const N: usize>( - &mut self, - ks: [&Q; N], - ) -> Option<[(&'_ K, &'_ mut V); N]> - where - Q: Hash + Equivalent<K>, - { - self.get_many_mut_inner(ks) - .map(|res| res.map(|(k, v)| (&*k, v))) - } - - /// Attempts to get mutable references to `N` values in the map at once, with immutable - /// references to the corresponding keys, without validating that the values are unique. - /// - /// Returns an array of length `N` with the results of each query. `None` will be returned if - /// any of the keys are missing. - /// - /// For a safe alternative see [`get_many_key_value_mut`](`HashMap::get_many_key_value_mut`). - /// - /// # Safety - /// - /// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting - /// references are not used. - /// - /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut libraries = HashMap::new(); - /// libraries.insert("Bodleian Library".to_string(), 1602); - /// libraries.insert("Athenæum".to_string(), 1807); - /// libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691); - /// libraries.insert("Library of Congress".to_string(), 1800); - /// - /// let got = libraries.get_many_key_value_mut([ - /// "Bodleian Library", - /// "Herzogin-Anna-Amalia-Bibliothek", - /// ]); - /// assert_eq!( - /// got, - /// Some([ - /// (&"Bodleian Library".to_string(), &mut 1602), - /// (&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691), - /// ]), - /// ); - /// // Missing keys result in None - /// let got = libraries.get_many_key_value_mut([ - /// "Bodleian Library", - /// "Gewandhaus", - /// ]); - /// assert_eq!(got, None); - /// ``` - pub unsafe fn get_many_key_value_unchecked_mut<Q: ?Sized, const N: usize>( - &mut self, - ks: [&Q; N], - ) -> Option<[(&'_ K, &'_ mut V); N]> - where - Q: Hash + Equivalent<K>, - { - self.get_many_unchecked_mut_inner(ks) - .map(|res| res.map(|(k, v)| (&*k, v))) - } - - fn get_many_mut_inner<Q: ?Sized, const N: usize>( - &mut self, - ks: [&Q; N], - ) -> Option<[&'_ mut (K, V); N]> - where - Q: Hash + Equivalent<K>, - { - let hashes = self.build_hashes_inner(ks); - self.table - .get_many_mut(hashes, |i, (k, _)| ks[i].equivalent(k)) - } - - unsafe fn get_many_unchecked_mut_inner<Q: ?Sized, const N: usize>( - &mut self, - ks: [&Q; N], - ) -> Option<[&'_ mut (K, V); N]> - where - Q: Hash + Equivalent<K>, - { - let hashes = self.build_hashes_inner(ks); - self.table - .get_many_unchecked_mut(hashes, |i, (k, _)| ks[i].equivalent(k)) - } - - fn build_hashes_inner<Q: ?Sized, const N: usize>(&self, ks: [&Q; N]) -> [u64; N] - where - Q: Hash + Equivalent<K>, - { - let mut hashes = [0_u64; N]; - for i in 0..N { - hashes[i] = make_hash::<Q, S>(&self.hash_builder, ks[i]); - } - hashes - } - - /// Inserts a key-value pair into the map. - /// - /// If the map did not have this key present, [`None`] is returned. - /// - /// If the map did have this key present, the value is updated, and the old - /// value is returned. The key is not updated, though; this matters for - /// types that can be `==` without being identical. See the [`std::collections`] - /// [module-level documentation] for more. - /// - /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None - /// [`std::collections`]: https://doc.rust-lang.org/std/collections/index.html - /// [module-level documentation]: https://doc.rust-lang.org/std/collections/index.html#insert-and-complex-keys - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// assert_eq!(map.insert(37, "a"), None); - /// assert_eq!(map.is_empty(), false); - /// - /// map.insert(37, "b"); - /// assert_eq!(map.insert(37, "c"), Some("b")); - /// assert_eq!(map[&37], "c"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(&mut self, k: K, v: V) -> Option<V> { - let hash = make_insert_hash::<K, S>(&self.hash_builder, &k); - if let Some((_, item)) = self.table.get_mut(hash, equivalent_key(&k)) { - Some(mem::replace(item, v)) - } else { - self.table - .insert(hash, (k, v), make_hasher::<_, V, S>(&self.hash_builder)); - None - } - } - - /// Insert a key-value pair into the map without checking - /// if the key already exists in the map. - /// - /// Returns a reference to the key and value just inserted. - /// - /// This operation is safe if a key does not exist in the map. - /// - /// However, if a key exists in the map already, the behavior is unspecified: - /// this operation may panic, loop forever, or any following operation with the map - /// may panic, loop forever or return arbitrary result. - /// - /// That said, this operation (and following operations) are guaranteed to - /// not violate memory safety. - /// - /// This operation is faster than regular insert, because it does not perform - /// lookup before insertion. - /// - /// This operation is useful during initial population of the map. - /// For example, when constructing a map from another map, we know - /// that keys are unique. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map1 = HashMap::new(); - /// assert_eq!(map1.insert(1, "a"), None); - /// assert_eq!(map1.insert(2, "b"), None); - /// assert_eq!(map1.insert(3, "c"), None); - /// assert_eq!(map1.len(), 3); - /// - /// let mut map2 = HashMap::new(); - /// - /// for (key, value) in map1.into_iter() { - /// map2.insert_unique_unchecked(key, value); - /// } - /// - /// let (key, value) = map2.insert_unique_unchecked(4, "d"); - /// assert_eq!(key, &4); - /// assert_eq!(value, &mut "d"); - /// *value = "e"; - /// - /// assert_eq!(map2[&1], "a"); - /// assert_eq!(map2[&2], "b"); - /// assert_eq!(map2[&3], "c"); - /// assert_eq!(map2[&4], "e"); - /// assert_eq!(map2.len(), 4); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert_unique_unchecked(&mut self, k: K, v: V) -> (&K, &mut V) { - let hash = make_insert_hash::<K, S>(&self.hash_builder, &k); - let bucket = self - .table - .insert(hash, (k, v), make_hasher::<_, V, S>(&self.hash_builder)); - let (k_ref, v_ref) = unsafe { bucket.as_mut() }; - (k_ref, v_ref) - } - - /// Tries to insert a key-value pair into the map, and returns - /// a mutable reference to the value in the entry. - /// - /// # Errors - /// - /// If the map already had this key present, nothing is updated, and - /// an error containing the occupied entry and the value is returned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::OccupiedError; - /// - /// let mut map = HashMap::new(); - /// assert_eq!(map.try_insert(37, "a").unwrap(), &"a"); - /// - /// match map.try_insert(37, "b") { - /// Err(OccupiedError { entry, value }) => { - /// assert_eq!(entry.key(), &37); - /// assert_eq!(entry.get(), &"a"); - /// assert_eq!(value, "b"); - /// } - /// _ => panic!() - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn try_insert( - &mut self, - key: K, - value: V, - ) -> Result<&mut V, OccupiedError<'_, K, V, S, A>> { - match self.entry(key) { - Entry::Occupied(entry) => Err(OccupiedError { entry, value }), - Entry::Vacant(entry) => Ok(entry.insert(value)), - } - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. Keeps the allocated memory for reuse. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// // The map is empty - /// assert!(map.is_empty() && map.capacity() == 0); - /// - /// map.insert(1, "a"); - /// - /// assert_eq!(map.remove(&1), Some("a")); - /// assert_eq!(map.remove(&1), None); - /// - /// // Now map holds none elements - /// assert!(map.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V> - where - Q: Hash + Equivalent<K>, - { - // Avoid `Option::map` because it bloats LLVM IR. - match self.remove_entry(k) { - Some((_, v)) => Some(v), - None => None, - } - } - - /// Removes a key from the map, returning the stored key and value if the - /// key was previously in the map. Keeps the allocated memory for reuse. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// // The map is empty - /// assert!(map.is_empty() && map.capacity() == 0); - /// - /// map.insert(1, "a"); - /// - /// assert_eq!(map.remove_entry(&1), Some((1, "a"))); - /// assert_eq!(map.remove(&1), None); - /// - /// // Now map hold none elements - /// assert!(map.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)> - where - Q: Hash + Equivalent<K>, - { - let hash = make_hash::<Q, S>(&self.hash_builder, k); - self.table.remove_entry(hash, equivalent_key(k)) - } -} - -impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> { - /// Creates a raw entry builder for the HashMap. - /// - /// Raw entries provide the lowest level of control for searching and - /// manipulating a map. They must be manually initialized with a hash and - /// then manually searched. After this, insertions into a vacant entry - /// still require an owned key to be provided. - /// - /// Raw entries are useful for such exotic situations as: - /// - /// * Hash memoization - /// * Deferring the creation of an owned key until it is known to be required - /// * Using a search key that doesn't work with the Borrow trait - /// * Using custom comparison logic without newtype wrappers - /// - /// Because raw entries provide much more low-level control, it's much easier - /// to put the HashMap into an inconsistent state which, while memory-safe, - /// will cause the map to produce seemingly random results. Higher-level and - /// more foolproof APIs like `entry` should be preferred when possible. - /// - /// In particular, the hash used to initialized the raw entry must still be - /// consistent with the hash of the key that is ultimately stored in the entry. - /// This is because implementations of HashMap may need to recompute hashes - /// when resizing, at which point only the keys are available. - /// - /// Raw entries give mutable access to the keys. This must not be used - /// to modify how the key would compare or hash, as the map will not re-evaluate - /// where the key should go, meaning the keys may become "lost" if their - /// location does not reflect their state. For instance, if you change a key - /// so that the map now contains keys which compare equal, search may start - /// acting erratically, with two keys randomly masking each other. Implementations - /// are free to assume this doesn't happen (within the limits of memory-safety). - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map = HashMap::new(); - /// map.extend([("a", 100), ("b", 200), ("c", 300)]); - /// - /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// - /// // Existing key (insert and update) - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => unreachable!(), - /// RawEntryMut::Occupied(mut view) => { - /// assert_eq!(view.get(), &100); - /// let v = view.get_mut(); - /// let new_v = (*v) * 10; - /// *v = new_v; - /// assert_eq!(view.insert(1111), 1000); - /// } - /// } - /// - /// assert_eq!(map[&"a"], 1111); - /// assert_eq!(map.len(), 3); - /// - /// // Existing key (take) - /// let hash = compute_hash(map.hasher(), &"c"); - /// match map.raw_entry_mut().from_key_hashed_nocheck(hash, &"c") { - /// RawEntryMut::Vacant(_) => unreachable!(), - /// RawEntryMut::Occupied(view) => { - /// assert_eq!(view.remove_entry(), ("c", 300)); - /// } - /// } - /// assert_eq!(map.raw_entry().from_key(&"c"), None); - /// assert_eq!(map.len(), 2); - /// - /// // Nonexistent key (insert and update) - /// let key = "d"; - /// let hash = compute_hash(map.hasher(), &key); - /// match map.raw_entry_mut().from_hash(hash, |q| *q == key) { - /// RawEntryMut::Occupied(_) => unreachable!(), - /// RawEntryMut::Vacant(view) => { - /// let (k, value) = view.insert("d", 4000); - /// assert_eq!((*k, *value), ("d", 4000)); - /// *value = 40000; - /// } - /// } - /// assert_eq!(map[&"d"], 40000); - /// assert_eq!(map.len(), 3); - /// - /// match map.raw_entry_mut().from_hash(hash, |q| *q == key) { - /// RawEntryMut::Vacant(_) => unreachable!(), - /// RawEntryMut::Occupied(view) => { - /// assert_eq!(view.remove_entry(), ("d", 40000)); - /// } - /// } - /// assert_eq!(map.get(&"d"), None); - /// assert_eq!(map.len(), 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S, A> { - RawEntryBuilderMut { map: self } - } - - /// Creates a raw immutable entry builder for the HashMap. - /// - /// Raw entries provide the lowest level of control for searching and - /// manipulating a map. They must be manually initialized with a hash and - /// then manually searched. - /// - /// This is useful for - /// * Hash memoization - /// * Using a search key that doesn't work with the Borrow trait - /// * Using custom comparison logic without newtype wrappers - /// - /// Unless you are in such a situation, higher-level and more foolproof APIs like - /// `get` should be preferred. - /// - /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`. - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.extend([("a", 100), ("b", 200), ("c", 300)]); - /// - /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// - /// for k in ["a", "b", "c", "d", "e", "f"] { - /// let hash = compute_hash(map.hasher(), k); - /// let v = map.get(&k).cloned(); - /// let kv = v.as_ref().map(|v| (&k, v)); - /// - /// println!("Key: {} and value: {:?}", k, v); - /// - /// assert_eq!(map.raw_entry().from_key(&k), kv); - /// assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv); - /// assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv); - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S, A> { - RawEntryBuilder { map: self } - } - - /// Returns a mutable reference to the [`RawTable`] used underneath [`HashMap`]. - /// This function is only available if the `raw` feature of the crate is enabled. - /// - /// # Note - /// - /// Calling this function is safe, but using the raw hash table API may require - /// unsafe functions or blocks. - /// - /// `RawTable` API gives the lowest level of control under the map that can be useful - /// for extending the HashMap's API, but may lead to *[undefined behavior]*. - /// - /// [`HashMap`]: struct.HashMap.html - /// [`RawTable`]: crate::raw::RawTable - /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.extend([("a", 10), ("b", 20), ("c", 30)]); - /// assert_eq!(map.len(), 3); - /// - /// // Let's imagine that we have a value and a hash of the key, but not the key itself. - /// // However, if you want to remove the value from the map by hash and value, and you - /// // know exactly that the value is unique, then you can create a function like this: - /// fn remove_by_hash<K, V, S, F>( - /// map: &mut HashMap<K, V, S>, - /// hash: u64, - /// is_match: F, - /// ) -> Option<(K, V)> - /// where - /// F: Fn(&(K, V)) -> bool, - /// { - /// let raw_table = map.raw_table(); - /// match raw_table.find(hash, is_match) { - /// Some(bucket) => Some(unsafe { raw_table.remove(bucket) }), - /// None => None, - /// } - /// } - /// - /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// - /// let hash = compute_hash(map.hasher(), "a"); - /// assert_eq!(remove_by_hash(&mut map, hash, |(_, v)| *v == 10), Some(("a", 10))); - /// assert_eq!(map.get(&"a"), None); - /// assert_eq!(map.len(), 2); - /// ``` - #[cfg(feature = "raw")] - #[cfg_attr(feature = "inline-more", inline)] - pub fn raw_table(&mut self) -> &mut RawTable<(K, V), A> { - &mut self.table - } -} - -impl<K, V, S, A> PartialEq for HashMap<K, V, S, A> -where - K: Eq + Hash, - V: PartialEq, - S: BuildHasher, - A: Allocator + Clone, -{ - fn eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - - self.iter() - .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) - } -} - -impl<K, V, S, A> Eq for HashMap<K, V, S, A> -where - K: Eq + Hash, - V: Eq, - S: BuildHasher, - A: Allocator + Clone, -{ -} - -impl<K, V, S, A> Debug for HashMap<K, V, S, A> -where - K: Debug, - V: Debug, - A: Allocator + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_map().entries(self.iter()).finish() - } -} - -impl<K, V, S, A> Default for HashMap<K, V, S, A> -where - S: Default, - A: Default + Allocator + Clone, -{ - /// Creates an empty `HashMap<K, V, S, A>`, with the `Default` value for the hasher and allocator. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use std::collections::hash_map::RandomState; - /// - /// // You can specify all types of HashMap, including hasher and allocator. - /// // Created map is empty and don't allocate memory - /// let map: HashMap<u32, String> = Default::default(); - /// assert_eq!(map.capacity(), 0); - /// let map: HashMap<u32, String, RandomState> = HashMap::default(); - /// assert_eq!(map.capacity(), 0); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn default() -> Self { - Self::with_hasher_in(Default::default(), Default::default()) - } -} - -impl<K, Q: ?Sized, V, S, A> Index<&Q> for HashMap<K, V, S, A> -where - K: Eq + Hash, - Q: Hash + Equivalent<K>, - S: BuildHasher, - A: Allocator + Clone, -{ - type Output = V; - - /// Returns a reference to the value corresponding to the supplied key. - /// - /// # Panics - /// - /// Panics if the key is not present in the `HashMap`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let map: HashMap<_, _> = [("a", "One"), ("b", "Two")].into(); - /// - /// assert_eq!(map[&"a"], "One"); - /// assert_eq!(map[&"b"], "Two"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn index(&self, key: &Q) -> &V { - self.get(key).expect("no entry found for key") - } -} - -// The default hasher is used to match the std implementation signature -#[cfg(feature = "ahash")] -impl<K, V, A, const N: usize> From<[(K, V); N]> for HashMap<K, V, DefaultHashBuilder, A> -where - K: Eq + Hash, - A: Default + Allocator + Clone, -{ - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let map1 = HashMap::from([(1, 2), (3, 4)]); - /// let map2: HashMap<_, _> = [(1, 2), (3, 4)].into(); - /// assert_eq!(map1, map2); - /// ``` - fn from(arr: [(K, V); N]) -> Self { - arr.into_iter().collect() - } -} - -/// An iterator over the entries of a `HashMap` in arbitrary order. -/// The iterator element type is `(&'a K, &'a V)`. -/// -/// This `struct` is created by the [`iter`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`iter`]: struct.HashMap.html#method.iter -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let map: HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into(); -/// -/// let mut iter = map.iter(); -/// let mut vec = vec![iter.next(), iter.next(), iter.next()]; -/// -/// // The `Iter` iterator produces items in arbitrary order, so the -/// // items must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [Some((&1, &"a")), Some((&2, &"b")), Some((&3, &"c"))]); -/// -/// // It is fused iterator -/// assert_eq!(iter.next(), None); -/// assert_eq!(iter.next(), None); -/// ``` -pub struct Iter<'a, K, V> { - inner: RawIter<(K, V)>, - marker: PhantomData<(&'a K, &'a V)>, -} - -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl<K, V> Clone for Iter<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Iter { - inner: self.inner.clone(), - marker: PhantomData, - } - } -} - -impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -/// A mutable iterator over the entries of a `HashMap` in arbitrary order. -/// The iterator element type is `(&'a K, &'a mut V)`. -/// -/// This `struct` is created by the [`iter_mut`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`iter_mut`]: struct.HashMap.html#method.iter_mut -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let mut map: HashMap<_, _> = [(1, "One".to_owned()), (2, "Two".into())].into(); -/// -/// let mut iter = map.iter_mut(); -/// iter.next().map(|(_, v)| v.push_str(" Mississippi")); -/// iter.next().map(|(_, v)| v.push_str(" Mississippi")); -/// -/// // It is fused iterator -/// assert_eq!(iter.next(), None); -/// assert_eq!(iter.next(), None); -/// -/// assert_eq!(map.get(&1).unwrap(), &"One Mississippi".to_owned()); -/// assert_eq!(map.get(&2).unwrap(), &"Two Mississippi".to_owned()); -/// ``` -pub struct IterMut<'a, K, V> { - inner: RawIter<(K, V)>, - // To ensure invariance with respect to V - marker: PhantomData<(&'a K, &'a mut V)>, -} - -// We override the default Send impl which has K: Sync instead of K: Send. Both -// are correct, but this one is more general since it allows keys which -// implement Send but not Sync. -unsafe impl<K: Send, V: Send> Send for IterMut<'_, K, V> {} - -impl<K, V> IterMut<'_, K, V> { - /// Returns a iterator of references over the remaining items. - #[cfg_attr(feature = "inline-more", inline)] - pub(super) fn iter(&self) -> Iter<'_, K, V> { - Iter { - inner: self.inner.clone(), - marker: PhantomData, - } - } -} - -/// An owning iterator over the entries of a `HashMap` in arbitrary order. -/// The iterator element type is `(K, V)`. -/// -/// This `struct` is created by the [`into_iter`] method on [`HashMap`] -/// (provided by the [`IntoIterator`] trait). See its documentation for more. -/// The map cannot be used after calling that method. -/// -/// [`into_iter`]: struct.HashMap.html#method.into_iter -/// [`HashMap`]: struct.HashMap.html -/// [`IntoIterator`]: https://doc.rust-lang.org/core/iter/trait.IntoIterator.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let map: HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into(); -/// -/// let mut iter = map.into_iter(); -/// let mut vec = vec![iter.next(), iter.next(), iter.next()]; -/// -/// // The `IntoIter` iterator produces items in arbitrary order, so the -/// // items must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [Some((1, "a")), Some((2, "b")), Some((3, "c"))]); -/// -/// // It is fused iterator -/// assert_eq!(iter.next(), None); -/// assert_eq!(iter.next(), None); -/// ``` -pub struct IntoIter<K, V, A: Allocator + Clone = Global> { - inner: RawIntoIter<(K, V), A>, -} - -impl<K, V, A: Allocator + Clone> IntoIter<K, V, A> { - /// Returns a iterator of references over the remaining items. - #[cfg_attr(feature = "inline-more", inline)] - pub(super) fn iter(&self) -> Iter<'_, K, V> { - Iter { - inner: self.inner.iter(), - marker: PhantomData, - } - } -} - -/// An owning iterator over the keys of a `HashMap` in arbitrary order. -/// The iterator element type is `K`. -/// -/// This `struct` is created by the [`into_keys`] method on [`HashMap`]. -/// See its documentation for more. -/// The map cannot be used after calling that method. -/// -/// [`into_keys`]: struct.HashMap.html#method.into_keys -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let map: HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into(); -/// -/// let mut keys = map.into_keys(); -/// let mut vec = vec![keys.next(), keys.next(), keys.next()]; -/// -/// // The `IntoKeys` iterator produces keys in arbitrary order, so the -/// // keys must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [Some(1), Some(2), Some(3)]); -/// -/// // It is fused iterator -/// assert_eq!(keys.next(), None); -/// assert_eq!(keys.next(), None); -/// ``` -pub struct IntoKeys<K, V, A: Allocator + Clone = Global> { - inner: IntoIter<K, V, A>, -} - -impl<K, V, A: Allocator + Clone> Iterator for IntoKeys<K, V, A> { - type Item = K; - - #[inline] - fn next(&mut self) -> Option<K> { - self.inner.next().map(|(k, _)| k) - } - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} - -impl<K, V, A: Allocator + Clone> ExactSizeIterator for IntoKeys<K, V, A> { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} - -impl<K, V, A: Allocator + Clone> FusedIterator for IntoKeys<K, V, A> {} - -impl<K: Debug, V: Debug, A: Allocator + Clone> fmt::Debug for IntoKeys<K, V, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list() - .entries(self.inner.iter().map(|(k, _)| k)) - .finish() - } -} - -/// An owning iterator over the values of a `HashMap` in arbitrary order. -/// The iterator element type is `V`. -/// -/// This `struct` is created by the [`into_values`] method on [`HashMap`]. -/// See its documentation for more. The map cannot be used after calling that method. -/// -/// [`into_values`]: struct.HashMap.html#method.into_values -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let map: HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into(); -/// -/// let mut values = map.into_values(); -/// let mut vec = vec![values.next(), values.next(), values.next()]; -/// -/// // The `IntoValues` iterator produces values in arbitrary order, so -/// // the values must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [Some("a"), Some("b"), Some("c")]); -/// -/// // It is fused iterator -/// assert_eq!(values.next(), None); -/// assert_eq!(values.next(), None); -/// ``` -pub struct IntoValues<K, V, A: Allocator + Clone = Global> { - inner: IntoIter<K, V, A>, -} - -impl<K, V, A: Allocator + Clone> Iterator for IntoValues<K, V, A> { - type Item = V; - - #[inline] - fn next(&mut self) -> Option<V> { - self.inner.next().map(|(_, v)| v) - } - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} - -impl<K, V, A: Allocator + Clone> ExactSizeIterator for IntoValues<K, V, A> { - #[inline] - fn len(&self) -> usize { - self.inner.len() - } -} - -impl<K, V, A: Allocator + Clone> FusedIterator for IntoValues<K, V, A> {} - -impl<K, V: Debug, A: Allocator + Clone> fmt::Debug for IntoValues<K, V, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list() - .entries(self.inner.iter().map(|(_, v)| v)) - .finish() - } -} - -/// An iterator over the keys of a `HashMap` in arbitrary order. -/// The iterator element type is `&'a K`. -/// -/// This `struct` is created by the [`keys`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`keys`]: struct.HashMap.html#method.keys -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let map: HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into(); -/// -/// let mut keys = map.keys(); -/// let mut vec = vec![keys.next(), keys.next(), keys.next()]; -/// -/// // The `Keys` iterator produces keys in arbitrary order, so the -/// // keys must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [Some(&1), Some(&2), Some(&3)]); -/// -/// // It is fused iterator -/// assert_eq!(keys.next(), None); -/// assert_eq!(keys.next(), None); -/// ``` -pub struct Keys<'a, K, V> { - inner: Iter<'a, K, V>, -} - -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl<K, V> Clone for Keys<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Keys { - inner: self.inner.clone(), - } - } -} - -impl<K: Debug, V> fmt::Debug for Keys<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -/// An iterator over the values of a `HashMap` in arbitrary order. -/// The iterator element type is `&'a V`. -/// -/// This `struct` is created by the [`values`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`values`]: struct.HashMap.html#method.values -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let map: HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into(); -/// -/// let mut values = map.values(); -/// let mut vec = vec![values.next(), values.next(), values.next()]; -/// -/// // The `Values` iterator produces values in arbitrary order, so the -/// // values must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [Some(&"a"), Some(&"b"), Some(&"c")]); -/// -/// // It is fused iterator -/// assert_eq!(values.next(), None); -/// assert_eq!(values.next(), None); -/// ``` -pub struct Values<'a, K, V> { - inner: Iter<'a, K, V>, -} - -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -impl<K, V> Clone for Values<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Values { - inner: self.inner.clone(), - } - } -} - -impl<K, V: Debug> fmt::Debug for Values<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -/// A draining iterator over the entries of a `HashMap` in arbitrary -/// order. The iterator element type is `(K, V)`. -/// -/// This `struct` is created by the [`drain`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`drain`]: struct.HashMap.html#method.drain -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let mut map: HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into(); -/// -/// let mut drain_iter = map.drain(); -/// let mut vec = vec![drain_iter.next(), drain_iter.next(), drain_iter.next()]; -/// -/// // The `Drain` iterator produces items in arbitrary order, so the -/// // items must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [Some((1, "a")), Some((2, "b")), Some((3, "c"))]); -/// -/// // It is fused iterator -/// assert_eq!(drain_iter.next(), None); -/// assert_eq!(drain_iter.next(), None); -/// ``` -pub struct Drain<'a, K, V, A: Allocator + Clone = Global> { - inner: RawDrain<'a, (K, V), A>, -} - -impl<K, V, A: Allocator + Clone> Drain<'_, K, V, A> { - /// Returns a iterator of references over the remaining items. - #[cfg_attr(feature = "inline-more", inline)] - pub(super) fn iter(&self) -> Iter<'_, K, V> { - Iter { - inner: self.inner.iter(), - marker: PhantomData, - } - } -} - -/// A draining iterator over entries of a `HashMap` which don't satisfy the predicate -/// `f(&k, &mut v)` in arbitrary order. The iterator element type is `(K, V)`. -/// -/// This `struct` is created by the [`drain_filter`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`drain_filter`]: struct.HashMap.html#method.drain_filter -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let mut map: HashMap<i32, &str> = [(1, "a"), (2, "b"), (3, "c")].into(); -/// -/// let mut drain_filter = map.drain_filter(|k, _v| k % 2 != 0); -/// let mut vec = vec![drain_filter.next(), drain_filter.next()]; -/// -/// // The `DrainFilter` iterator produces items in arbitrary order, so the -/// // items must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [Some((1, "a")),Some((3, "c"))]); -/// -/// // It is fused iterator -/// assert_eq!(drain_filter.next(), None); -/// assert_eq!(drain_filter.next(), None); -/// drop(drain_filter); -/// -/// assert_eq!(map.len(), 1); -/// ``` -pub struct DrainFilter<'a, K, V, F, A: Allocator + Clone = Global> -where - F: FnMut(&K, &mut V) -> bool, -{ - f: F, - inner: DrainFilterInner<'a, K, V, A>, -} - -impl<'a, K, V, F, A> Drop for DrainFilter<'a, K, V, F, A> -where - F: FnMut(&K, &mut V) -> bool, - A: Allocator + Clone, -{ - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - while let Some(item) = self.next() { - let guard = ConsumeAllOnDrop(self); - drop(item); - mem::forget(guard); - } - } -} - -pub(super) struct ConsumeAllOnDrop<'a, T: Iterator>(pub &'a mut T); - -impl<T: Iterator> Drop for ConsumeAllOnDrop<'_, T> { - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - self.0.for_each(drop); - } -} - -impl<K, V, F, A> Iterator for DrainFilter<'_, K, V, F, A> -where - F: FnMut(&K, &mut V) -> bool, - A: Allocator + Clone, -{ - type Item = (K, V); - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<Self::Item> { - self.inner.next(&mut self.f) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - (0, self.inner.iter.size_hint().1) - } -} - -impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {} - -/// Portions of `DrainFilter` shared with `set::DrainFilter` -pub(super) struct DrainFilterInner<'a, K, V, A: Allocator + Clone> { - pub iter: RawIter<(K, V)>, - pub table: &'a mut RawTable<(K, V), A>, -} - -impl<K, V, A: Allocator + Clone> DrainFilterInner<'_, K, V, A> { - #[cfg_attr(feature = "inline-more", inline)] - pub(super) fn next<F>(&mut self, f: &mut F) -> Option<(K, V)> - where - F: FnMut(&K, &mut V) -> bool, - { - unsafe { - for item in &mut self.iter { - let &mut (ref key, ref mut value) = item.as_mut(); - if f(key, value) { - return Some(self.table.remove(item)); - } - } - } - None - } -} - -/// A mutable iterator over the values of a `HashMap` in arbitrary order. -/// The iterator element type is `&'a mut V`. -/// -/// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its -/// documentation for more. -/// -/// [`values_mut`]: struct.HashMap.html#method.values_mut -/// [`HashMap`]: struct.HashMap.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashMap; -/// -/// let mut map: HashMap<_, _> = [(1, "One".to_owned()), (2, "Two".into())].into(); -/// -/// let mut values = map.values_mut(); -/// values.next().map(|v| v.push_str(" Mississippi")); -/// values.next().map(|v| v.push_str(" Mississippi")); -/// -/// // It is fused iterator -/// assert_eq!(values.next(), None); -/// assert_eq!(values.next(), None); -/// -/// assert_eq!(map.get(&1).unwrap(), &"One Mississippi".to_owned()); -/// assert_eq!(map.get(&2).unwrap(), &"Two Mississippi".to_owned()); -/// ``` -pub struct ValuesMut<'a, K, V> { - inner: IterMut<'a, K, V>, -} - -/// A builder for computing where in a [`HashMap`] a key-value pair would be stored. -/// -/// See the [`HashMap::raw_entry_mut`] docs for usage examples. -/// -/// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{RawEntryBuilderMut, RawEntryMut::Vacant, RawEntryMut::Occupied}; -/// use hashbrown::HashMap; -/// use core::hash::{BuildHasher, Hash}; -/// -/// let mut map = HashMap::new(); -/// map.extend([(1, 11), (2, 12), (3, 13), (4, 14), (5, 15), (6, 16)]); -/// assert_eq!(map.len(), 6); -/// -/// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { -/// use core::hash::Hasher; -/// let mut state = hash_builder.build_hasher(); -/// key.hash(&mut state); -/// state.finish() -/// } -/// -/// let builder: RawEntryBuilderMut<_, _, _> = map.raw_entry_mut(); -/// -/// // Existing key -/// match builder.from_key(&6) { -/// Vacant(_) => unreachable!(), -/// Occupied(view) => assert_eq!(view.get(), &16), -/// } -/// -/// for key in 0..12 { -/// let hash = compute_hash(map.hasher(), &key); -/// let value = map.get(&key).cloned(); -/// let key_value = value.as_ref().map(|v| (&key, v)); -/// -/// println!("Key: {} and value: {:?}", key, value); -/// -/// match map.raw_entry_mut().from_key(&key) { -/// Occupied(mut o) => assert_eq!(Some(o.get_key_value()), key_value), -/// Vacant(_) => assert_eq!(value, None), -/// } -/// match map.raw_entry_mut().from_key_hashed_nocheck(hash, &key) { -/// Occupied(mut o) => assert_eq!(Some(o.get_key_value()), key_value), -/// Vacant(_) => assert_eq!(value, None), -/// } -/// match map.raw_entry_mut().from_hash(hash, |q| *q == key) { -/// Occupied(mut o) => assert_eq!(Some(o.get_key_value()), key_value), -/// Vacant(_) => assert_eq!(value, None), -/// } -/// } -/// -/// assert_eq!(map.len(), 6); -/// ``` -pub struct RawEntryBuilderMut<'a, K, V, S, A: Allocator + Clone = Global> { - map: &'a mut HashMap<K, V, S, A>, -} - -/// A view into a single entry in a map, which may either be vacant or occupied. -/// -/// This is a lower-level version of [`Entry`]. -/// -/// This `enum` is constructed through the [`raw_entry_mut`] method on [`HashMap`], -/// then calling one of the methods of that [`RawEntryBuilderMut`]. -/// -/// [`HashMap`]: struct.HashMap.html -/// [`Entry`]: enum.Entry.html -/// [`raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut -/// [`RawEntryBuilderMut`]: struct.RawEntryBuilderMut.html -/// -/// # Examples -/// -/// ``` -/// use core::hash::{BuildHasher, Hash}; -/// use hashbrown::hash_map::{HashMap, RawEntryMut, RawOccupiedEntryMut}; -/// -/// let mut map = HashMap::new(); -/// map.extend([('a', 1), ('b', 2), ('c', 3)]); -/// assert_eq!(map.len(), 3); -/// -/// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { -/// use core::hash::Hasher; -/// let mut state = hash_builder.build_hasher(); -/// key.hash(&mut state); -/// state.finish() -/// } -/// -/// // Existing key (insert) -/// let raw: RawEntryMut<_, _, _> = map.raw_entry_mut().from_key(&'a'); -/// let _raw_o: RawOccupiedEntryMut<_, _, _> = raw.insert('a', 10); -/// assert_eq!(map.len(), 3); -/// -/// // Nonexistent key (insert) -/// map.raw_entry_mut().from_key(&'d').insert('d', 40); -/// assert_eq!(map.len(), 4); -/// -/// // Existing key (or_insert) -/// let hash = compute_hash(map.hasher(), &'b'); -/// let kv = map -/// .raw_entry_mut() -/// .from_key_hashed_nocheck(hash, &'b') -/// .or_insert('b', 20); -/// assert_eq!(kv, (&mut 'b', &mut 2)); -/// *kv.1 = 20; -/// assert_eq!(map.len(), 4); -/// -/// // Nonexistent key (or_insert) -/// let hash = compute_hash(map.hasher(), &'e'); -/// let kv = map -/// .raw_entry_mut() -/// .from_key_hashed_nocheck(hash, &'e') -/// .or_insert('e', 50); -/// assert_eq!(kv, (&mut 'e', &mut 50)); -/// assert_eq!(map.len(), 5); -/// -/// // Existing key (or_insert_with) -/// let hash = compute_hash(map.hasher(), &'c'); -/// let kv = map -/// .raw_entry_mut() -/// .from_hash(hash, |q| q == &'c') -/// .or_insert_with(|| ('c', 30)); -/// assert_eq!(kv, (&mut 'c', &mut 3)); -/// *kv.1 = 30; -/// assert_eq!(map.len(), 5); -/// -/// // Nonexistent key (or_insert_with) -/// let hash = compute_hash(map.hasher(), &'f'); -/// let kv = map -/// .raw_entry_mut() -/// .from_hash(hash, |q| q == &'f') -/// .or_insert_with(|| ('f', 60)); -/// assert_eq!(kv, (&mut 'f', &mut 60)); -/// assert_eq!(map.len(), 6); -/// -/// println!("Our HashMap: {:?}", map); -/// -/// let mut vec: Vec<_> = map.iter().map(|(&k, &v)| (k, v)).collect(); -/// // The `Iter` iterator produces items in arbitrary order, so the -/// // items must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [('a', 10), ('b', 20), ('c', 30), ('d', 40), ('e', 50), ('f', 60)]); -/// ``` -pub enum RawEntryMut<'a, K, V, S, A: Allocator + Clone = Global> { - /// An occupied entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::{hash_map::RawEntryMut, HashMap}; - /// let mut map: HashMap<_, _> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => unreachable!(), - /// RawEntryMut::Occupied(_) => { } - /// } - /// ``` - Occupied(RawOccupiedEntryMut<'a, K, V, S, A>), - /// A vacant entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::{hash_map::RawEntryMut, HashMap}; - /// let mut map: HashMap<&str, i32> = HashMap::new(); - /// - /// match map.raw_entry_mut().from_key("a") { - /// RawEntryMut::Occupied(_) => unreachable!(), - /// RawEntryMut::Vacant(_) => { } - /// } - /// ``` - Vacant(RawVacantEntryMut<'a, K, V, S, A>), -} - -/// A view into an occupied entry in a `HashMap`. -/// It is part of the [`RawEntryMut`] enum. -/// -/// [`RawEntryMut`]: enum.RawEntryMut.html -/// -/// # Examples -/// -/// ``` -/// use core::hash::{BuildHasher, Hash}; -/// use hashbrown::hash_map::{HashMap, RawEntryMut, RawOccupiedEntryMut}; -/// -/// let mut map = HashMap::new(); -/// map.extend([("a", 10), ("b", 20), ("c", 30)]); -/// -/// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { -/// use core::hash::Hasher; -/// let mut state = hash_builder.build_hasher(); -/// key.hash(&mut state); -/// state.finish() -/// } -/// -/// let _raw_o: RawOccupiedEntryMut<_, _, _> = map.raw_entry_mut().from_key(&"a").insert("a", 100); -/// assert_eq!(map.len(), 3); -/// -/// // Existing key (insert and update) -/// match map.raw_entry_mut().from_key(&"a") { -/// RawEntryMut::Vacant(_) => unreachable!(), -/// RawEntryMut::Occupied(mut view) => { -/// assert_eq!(view.get(), &100); -/// let v = view.get_mut(); -/// let new_v = (*v) * 10; -/// *v = new_v; -/// assert_eq!(view.insert(1111), 1000); -/// } -/// } -/// -/// assert_eq!(map[&"a"], 1111); -/// assert_eq!(map.len(), 3); -/// -/// // Existing key (take) -/// let hash = compute_hash(map.hasher(), &"c"); -/// match map.raw_entry_mut().from_key_hashed_nocheck(hash, &"c") { -/// RawEntryMut::Vacant(_) => unreachable!(), -/// RawEntryMut::Occupied(view) => { -/// assert_eq!(view.remove_entry(), ("c", 30)); -/// } -/// } -/// assert_eq!(map.raw_entry().from_key(&"c"), None); -/// assert_eq!(map.len(), 2); -/// -/// let hash = compute_hash(map.hasher(), &"b"); -/// match map.raw_entry_mut().from_hash(hash, |q| *q == "b") { -/// RawEntryMut::Vacant(_) => unreachable!(), -/// RawEntryMut::Occupied(view) => { -/// assert_eq!(view.remove_entry(), ("b", 20)); -/// } -/// } -/// assert_eq!(map.get(&"b"), None); -/// assert_eq!(map.len(), 1); -/// ``` -pub struct RawOccupiedEntryMut<'a, K, V, S, A: Allocator + Clone = Global> { - elem: Bucket<(K, V)>, - table: &'a mut RawTable<(K, V), A>, - hash_builder: &'a S, -} - -unsafe impl<K, V, S, A> Send for RawOccupiedEntryMut<'_, K, V, S, A> -where - K: Send, - V: Send, - S: Send, - A: Send + Allocator + Clone, -{ -} -unsafe impl<K, V, S, A> Sync for RawOccupiedEntryMut<'_, K, V, S, A> -where - K: Sync, - V: Sync, - S: Sync, - A: Sync + Allocator + Clone, -{ -} - -/// A view into a vacant entry in a `HashMap`. -/// It is part of the [`RawEntryMut`] enum. -/// -/// [`RawEntryMut`]: enum.RawEntryMut.html -/// -/// # Examples -/// -/// ``` -/// use core::hash::{BuildHasher, Hash}; -/// use hashbrown::hash_map::{HashMap, RawEntryMut, RawVacantEntryMut}; -/// -/// let mut map = HashMap::<&str, i32>::new(); -/// -/// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { -/// use core::hash::Hasher; -/// let mut state = hash_builder.build_hasher(); -/// key.hash(&mut state); -/// state.finish() -/// } -/// -/// let raw_v: RawVacantEntryMut<_, _, _> = match map.raw_entry_mut().from_key(&"a") { -/// RawEntryMut::Vacant(view) => view, -/// RawEntryMut::Occupied(_) => unreachable!(), -/// }; -/// raw_v.insert("a", 10); -/// assert!(map[&"a"] == 10 && map.len() == 1); -/// -/// // Nonexistent key (insert and update) -/// let hash = compute_hash(map.hasher(), &"b"); -/// match map.raw_entry_mut().from_key_hashed_nocheck(hash, &"b") { -/// RawEntryMut::Occupied(_) => unreachable!(), -/// RawEntryMut::Vacant(view) => { -/// let (k, value) = view.insert("b", 2); -/// assert_eq!((*k, *value), ("b", 2)); -/// *value = 20; -/// } -/// } -/// assert!(map[&"b"] == 20 && map.len() == 2); -/// -/// let hash = compute_hash(map.hasher(), &"c"); -/// match map.raw_entry_mut().from_hash(hash, |q| *q == "c") { -/// RawEntryMut::Occupied(_) => unreachable!(), -/// RawEntryMut::Vacant(view) => { -/// assert_eq!(view.insert("c", 30), (&mut "c", &mut 30)); -/// } -/// } -/// assert!(map[&"c"] == 30 && map.len() == 3); -/// ``` -pub struct RawVacantEntryMut<'a, K, V, S, A: Allocator + Clone = Global> { - table: &'a mut RawTable<(K, V), A>, - hash_builder: &'a S, -} - -/// A builder for computing where in a [`HashMap`] a key-value pair would be stored. -/// -/// See the [`HashMap::raw_entry`] docs for usage examples. -/// -/// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{HashMap, RawEntryBuilder}; -/// use core::hash::{BuildHasher, Hash}; -/// -/// let mut map = HashMap::new(); -/// map.extend([(1, 10), (2, 20), (3, 30)]); -/// -/// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { -/// use core::hash::Hasher; -/// let mut state = hash_builder.build_hasher(); -/// key.hash(&mut state); -/// state.finish() -/// } -/// -/// for k in 0..6 { -/// let hash = compute_hash(map.hasher(), &k); -/// let v = map.get(&k).cloned(); -/// let kv = v.as_ref().map(|v| (&k, v)); -/// -/// println!("Key: {} and value: {:?}", k, v); -/// let builder: RawEntryBuilder<_, _, _> = map.raw_entry(); -/// assert_eq!(builder.from_key(&k), kv); -/// assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv); -/// assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv); -/// } -/// ``` -pub struct RawEntryBuilder<'a, K, V, S, A: Allocator + Clone = Global> { - map: &'a HashMap<K, V, S, A>, -} - -impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilderMut<'a, K, V, S, A> { - /// Creates a `RawEntryMut` from the given key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// let key = "a"; - /// let entry: RawEntryMut<&str, u32, _> = map.raw_entry_mut().from_key(&key); - /// entry.insert(key, 100); - /// assert_eq!(map[&"a"], 100); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - #[allow(clippy::wrong_self_convention)] - pub fn from_key<Q: ?Sized>(self, k: &Q) -> RawEntryMut<'a, K, V, S, A> - where - S: BuildHasher, - Q: Hash + Equivalent<K>, - { - let hash = make_hash::<Q, S>(&self.map.hash_builder, k); - self.from_key_hashed_nocheck(hash, k) - } - - /// Creates a `RawEntryMut` from the given key and its hash. - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// let key = "a"; - /// let hash = compute_hash(map.hasher(), &key); - /// let entry: RawEntryMut<&str, u32, _> = map.raw_entry_mut().from_key_hashed_nocheck(hash, &key); - /// entry.insert(key, 100); - /// assert_eq!(map[&"a"], 100); - /// ``` - #[inline] - #[allow(clippy::wrong_self_convention)] - pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S, A> - where - Q: Equivalent<K>, - { - self.from_hash(hash, equivalent(k)) - } -} - -impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilderMut<'a, K, V, S, A> { - /// Creates a `RawEntryMut` from the given hash and matching function. - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// let key = "a"; - /// let hash = compute_hash(map.hasher(), &key); - /// let entry: RawEntryMut<&str, u32, _> = map.raw_entry_mut().from_hash(hash, |k| k == &key); - /// entry.insert(key, 100); - /// assert_eq!(map[&"a"], 100); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - #[allow(clippy::wrong_self_convention)] - pub fn from_hash<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S, A> - where - for<'b> F: FnMut(&'b K) -> bool, - { - self.search(hash, is_match) - } - - #[cfg_attr(feature = "inline-more", inline)] - fn search<F>(self, hash: u64, mut is_match: F) -> RawEntryMut<'a, K, V, S, A> - where - for<'b> F: FnMut(&'b K) -> bool, - { - match self.map.table.find(hash, |(k, _)| is_match(k)) { - Some(elem) => RawEntryMut::Occupied(RawOccupiedEntryMut { - elem, - table: &mut self.map.table, - hash_builder: &self.map.hash_builder, - }), - None => RawEntryMut::Vacant(RawVacantEntryMut { - table: &mut self.map.table, - hash_builder: &self.map.hash_builder, - }), - } - } -} - -impl<'a, K, V, S, A: Allocator + Clone> RawEntryBuilder<'a, K, V, S, A> { - /// Access an immutable entry by key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// let key = "a"; - /// assert_eq!(map.raw_entry().from_key(&key), Some((&"a", &100))); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - #[allow(clippy::wrong_self_convention)] - pub fn from_key<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)> - where - S: BuildHasher, - Q: Hash + Equivalent<K>, - { - let hash = make_hash::<Q, S>(&self.map.hash_builder, k); - self.from_key_hashed_nocheck(hash, k) - } - - /// Access an immutable entry by a key and its hash. - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::HashMap; - /// - /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// - /// let map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// let key = "a"; - /// let hash = compute_hash(map.hasher(), &key); - /// assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &key), Some((&"a", &100))); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - #[allow(clippy::wrong_self_convention)] - pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> - where - Q: Equivalent<K>, - { - self.from_hash(hash, equivalent(k)) - } - - #[cfg_attr(feature = "inline-more", inline)] - fn search<F>(self, hash: u64, mut is_match: F) -> Option<(&'a K, &'a V)> - where - F: FnMut(&K) -> bool, - { - match self.map.table.get(hash, |(k, _)| is_match(k)) { - Some(&(ref key, ref value)) => Some((key, value)), - None => None, - } - } - - /// Access an immutable entry by hash and matching function. - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::HashMap; - /// - /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// - /// let map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// let key = "a"; - /// let hash = compute_hash(map.hasher(), &key); - /// assert_eq!(map.raw_entry().from_hash(hash, |k| k == &key), Some((&"a", &100))); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - #[allow(clippy::wrong_self_convention)] - pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> - where - F: FnMut(&K) -> bool, - { - self.search(hash, is_match) - } -} - -impl<'a, K, V, S, A: Allocator + Clone> RawEntryMut<'a, K, V, S, A> { - /// Sets the value of the entry, and returns a RawOccupiedEntryMut. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// let entry = map.raw_entry_mut().from_key("horseyland").insert("horseyland", 37); - /// - /// assert_eq!(entry.remove_entry(), ("horseyland", 37)); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V, S, A> - where - K: Hash, - S: BuildHasher, - { - match self { - RawEntryMut::Occupied(mut entry) => { - entry.insert(value); - entry - } - RawEntryMut::Vacant(entry) => entry.insert_entry(key, value), - } - } - - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// mutable references to the key and value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3); - /// assert_eq!(map["poneyland"], 3); - /// - /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - match self { - RawEntryMut::Occupied(entry) => entry.into_key_value(), - RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val), - } - } - - /// Ensures a value is in the entry by inserting the result of the default function if empty, - /// and returns mutable references to the key and value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, String> = HashMap::new(); - /// - /// map.raw_entry_mut().from_key("poneyland").or_insert_with(|| { - /// ("poneyland", "hoho".to_string()) - /// }); - /// - /// assert_eq!(map["poneyland"], "hoho".to_string()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert_with<F>(self, default: F) -> (&'a mut K, &'a mut V) - where - F: FnOnce() -> (K, V), - K: Hash, - S: BuildHasher, - { - match self { - RawEntryMut::Occupied(entry) => entry.into_key_value(), - RawEntryMut::Vacant(entry) => { - let (k, v) = default(); - entry.insert(k, v) - } - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.raw_entry_mut() - /// .from_key("poneyland") - /// .and_modify(|_k, v| { *v += 1 }) - /// .or_insert("poneyland", 42); - /// assert_eq!(map["poneyland"], 42); - /// - /// map.raw_entry_mut() - /// .from_key("poneyland") - /// .and_modify(|_k, v| { *v += 1 }) - /// .or_insert("poneyland", 0); - /// assert_eq!(map["poneyland"], 43); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn and_modify<F>(self, f: F) -> Self - where - F: FnOnce(&mut K, &mut V), - { - match self { - RawEntryMut::Occupied(mut entry) => { - { - let (k, v) = entry.get_key_value_mut(); - f(k, v); - } - RawEntryMut::Occupied(entry) - } - RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry), - } - } - - /// Provides shared access to the key and owned access to the value of - /// an occupied entry and allows to replace or remove it based on the - /// value of the returned option. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RawEntryMut; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// let entry = map - /// .raw_entry_mut() - /// .from_key("poneyland") - /// .and_replace_entry_with(|_k, _v| panic!()); - /// - /// match entry { - /// RawEntryMut::Vacant(_) => {}, - /// RawEntryMut::Occupied(_) => panic!(), - /// } - /// - /// map.insert("poneyland", 42); - /// - /// let entry = map - /// .raw_entry_mut() - /// .from_key("poneyland") - /// .and_replace_entry_with(|k, v| { - /// assert_eq!(k, &"poneyland"); - /// assert_eq!(v, 42); - /// Some(v + 1) - /// }); - /// - /// match entry { - /// RawEntryMut::Occupied(e) => { - /// assert_eq!(e.key(), &"poneyland"); - /// assert_eq!(e.get(), &43); - /// }, - /// RawEntryMut::Vacant(_) => panic!(), - /// } - /// - /// assert_eq!(map["poneyland"], 43); - /// - /// let entry = map - /// .raw_entry_mut() - /// .from_key("poneyland") - /// .and_replace_entry_with(|_k, _v| None); - /// - /// match entry { - /// RawEntryMut::Vacant(_) => {}, - /// RawEntryMut::Occupied(_) => panic!(), - /// } - /// - /// assert!(!map.contains_key("poneyland")); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn and_replace_entry_with<F>(self, f: F) -> Self - where - F: FnOnce(&K, V) -> Option<V>, - { - match self { - RawEntryMut::Occupied(entry) => entry.replace_entry_with(f), - RawEntryMut::Vacant(_) => self, - } - } -} - -impl<'a, K, V, S, A: Allocator + Clone> RawOccupiedEntryMut<'a, K, V, S, A> { - /// Gets a reference to the key in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => assert_eq!(o.key(), &"a") - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &K { - unsafe { &self.elem.as_ref().0 } - } - - /// Gets a mutable reference to the key in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// use std::rc::Rc; - /// - /// let key_one = Rc::new("a"); - /// let key_two = Rc::new("a"); - /// - /// let mut map: HashMap<Rc<&str>, u32> = HashMap::new(); - /// map.insert(key_one.clone(), 10); - /// - /// assert_eq!(map[&key_one], 10); - /// assert!(Rc::strong_count(&key_one) == 2 && Rc::strong_count(&key_two) == 1); - /// - /// match map.raw_entry_mut().from_key(&key_one) { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(mut o) => { - /// *o.key_mut() = key_two.clone(); - /// } - /// } - /// assert_eq!(map[&key_two], 10); - /// assert!(Rc::strong_count(&key_one) == 1 && Rc::strong_count(&key_two) == 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key_mut(&mut self) -> &mut K { - unsafe { &mut self.elem.as_mut().0 } - } - - /// Converts the entry into a mutable reference to the key in the entry - /// with a lifetime bound to the map itself. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// use std::rc::Rc; - /// - /// let key_one = Rc::new("a"); - /// let key_two = Rc::new("a"); - /// - /// let mut map: HashMap<Rc<&str>, u32> = HashMap::new(); - /// map.insert(key_one.clone(), 10); - /// - /// assert_eq!(map[&key_one], 10); - /// assert!(Rc::strong_count(&key_one) == 2 && Rc::strong_count(&key_two) == 1); - /// - /// let inside_key: &mut Rc<&str>; - /// - /// match map.raw_entry_mut().from_key(&key_one) { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => inside_key = o.into_key(), - /// } - /// *inside_key = key_two.clone(); - /// - /// assert_eq!(map[&key_two], 10); - /// assert!(Rc::strong_count(&key_one) == 1 && Rc::strong_count(&key_two) == 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_key(self) -> &'a mut K { - unsafe { &mut self.elem.as_mut().0 } - } - - /// Gets a reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => assert_eq!(o.get(), &100), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get(&self) -> &V { - unsafe { &self.elem.as_ref().1 } - } - - /// Converts the OccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// let value: &mut u32; - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => value = o.into_mut(), - /// } - /// *value += 900; - /// - /// assert_eq!(map[&"a"], 1000); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_mut(self) -> &'a mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Gets a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(mut o) => *o.get_mut() += 900, - /// } - /// - /// assert_eq!(map[&"a"], 1000); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_mut(&mut self) -> &mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Gets a reference to the key and value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => assert_eq!(o.get_key_value(), (&"a", &100)), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_key_value(&self) -> (&K, &V) { - unsafe { - let &(ref key, ref value) = self.elem.as_ref(); - (key, value) - } - } - - /// Gets a mutable reference to the key and value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// use std::rc::Rc; - /// - /// let key_one = Rc::new("a"); - /// let key_two = Rc::new("a"); - /// - /// let mut map: HashMap<Rc<&str>, u32> = HashMap::new(); - /// map.insert(key_one.clone(), 10); - /// - /// assert_eq!(map[&key_one], 10); - /// assert!(Rc::strong_count(&key_one) == 2 && Rc::strong_count(&key_two) == 1); - /// - /// match map.raw_entry_mut().from_key(&key_one) { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(mut o) => { - /// let (inside_key, inside_value) = o.get_key_value_mut(); - /// *inside_key = key_two.clone(); - /// *inside_value = 100; - /// } - /// } - /// assert_eq!(map[&key_two], 100); - /// assert!(Rc::strong_count(&key_one) == 1 && Rc::strong_count(&key_two) == 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { - unsafe { - let &mut (ref mut key, ref mut value) = self.elem.as_mut(); - (key, value) - } - } - - /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry - /// with a lifetime bound to the map itself. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// use std::rc::Rc; - /// - /// let key_one = Rc::new("a"); - /// let key_two = Rc::new("a"); - /// - /// let mut map: HashMap<Rc<&str>, u32> = HashMap::new(); - /// map.insert(key_one.clone(), 10); - /// - /// assert_eq!(map[&key_one], 10); - /// assert!(Rc::strong_count(&key_one) == 2 && Rc::strong_count(&key_two) == 1); - /// - /// let inside_key: &mut Rc<&str>; - /// let inside_value: &mut u32; - /// match map.raw_entry_mut().from_key(&key_one) { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => { - /// let tuple = o.into_key_value(); - /// inside_key = tuple.0; - /// inside_value = tuple.1; - /// } - /// } - /// *inside_key = key_two.clone(); - /// *inside_value = 100; - /// assert_eq!(map[&key_two], 100); - /// assert!(Rc::strong_count(&key_one) == 1 && Rc::strong_count(&key_two) == 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { - unsafe { - let &mut (ref mut key, ref mut value) = self.elem.as_mut(); - (key, value) - } - } - - /// Sets the value of the entry, and returns the entry's old value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(mut o) => assert_eq!(o.insert(1000), 100), - /// } - /// - /// assert_eq!(map[&"a"], 1000); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(&mut self, value: V) -> V { - mem::replace(self.get_mut(), value) - } - - /// Sets the value of the entry, and returns the entry's old value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// use std::rc::Rc; - /// - /// let key_one = Rc::new("a"); - /// let key_two = Rc::new("a"); - /// - /// let mut map: HashMap<Rc<&str>, u32> = HashMap::new(); - /// map.insert(key_one.clone(), 10); - /// - /// assert_eq!(map[&key_one], 10); - /// assert!(Rc::strong_count(&key_one) == 2 && Rc::strong_count(&key_two) == 1); - /// - /// match map.raw_entry_mut().from_key(&key_one) { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(mut o) => { - /// let old_key = o.insert_key(key_two.clone()); - /// assert!(Rc::ptr_eq(&old_key, &key_one)); - /// } - /// } - /// assert_eq!(map[&key_two], 10); - /// assert!(Rc::strong_count(&key_one) == 1 && Rc::strong_count(&key_two) == 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert_key(&mut self, key: K) -> K { - mem::replace(self.key_mut(), key) - } - - /// Takes the value out of the entry, and returns it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => assert_eq!(o.remove(), 100), - /// } - /// assert_eq!(map.get(&"a"), None); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove(self) -> V { - self.remove_entry().1 - } - - /// Take the ownership of the key and value from the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => assert_eq!(o.remove_entry(), ("a", 100)), - /// } - /// assert_eq!(map.get(&"a"), None); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove_entry(self) -> (K, V) { - unsafe { self.table.remove(self.elem) } - } - - /// Provides shared access to the key and owned access to the value of - /// the entry and allows to replace or remove it based on the - /// value of the returned option. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// let raw_entry = match map.raw_entry_mut().from_key(&"a") { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => o.replace_entry_with(|k, v| { - /// assert_eq!(k, &"a"); - /// assert_eq!(v, 100); - /// Some(v + 900) - /// }), - /// }; - /// let raw_entry = match raw_entry { - /// RawEntryMut::Vacant(_) => panic!(), - /// RawEntryMut::Occupied(o) => o.replace_entry_with(|k, v| { - /// assert_eq!(k, &"a"); - /// assert_eq!(v, 1000); - /// None - /// }), - /// }; - /// match raw_entry { - /// RawEntryMut::Vacant(_) => { }, - /// RawEntryMut::Occupied(_) => panic!(), - /// }; - /// assert_eq!(map.get(&"a"), None); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_entry_with<F>(self, f: F) -> RawEntryMut<'a, K, V, S, A> - where - F: FnOnce(&K, V) -> Option<V>, - { - unsafe { - let still_occupied = self - .table - .replace_bucket_with(self.elem.clone(), |(key, value)| { - f(&key, value).map(|new_value| (key, new_value)) - }); - - if still_occupied { - RawEntryMut::Occupied(self) - } else { - RawEntryMut::Vacant(RawVacantEntryMut { - table: self.table, - hash_builder: self.hash_builder, - }) - } - } - } -} - -impl<'a, K, V, S, A: Allocator + Clone> RawVacantEntryMut<'a, K, V, S, A> { - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// - /// match map.raw_entry_mut().from_key(&"c") { - /// RawEntryMut::Occupied(_) => panic!(), - /// RawEntryMut::Vacant(v) => assert_eq!(v.insert("c", 300), (&mut "c", &mut 300)), - /// } - /// - /// assert_eq!(map[&"c"], 300); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - let hash = make_insert_hash::<K, S>(self.hash_builder, &key); - self.insert_hashed_nocheck(hash, key, value) - } - - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it. - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// - /// let mut map: HashMap<&str, u32> = [("a", 100), ("b", 200)].into(); - /// let key = "c"; - /// let hash = compute_hash(map.hasher(), &key); - /// - /// match map.raw_entry_mut().from_key_hashed_nocheck(hash, &key) { - /// RawEntryMut::Occupied(_) => panic!(), - /// RawEntryMut::Vacant(v) => assert_eq!( - /// v.insert_hashed_nocheck(hash, key, 300), - /// (&mut "c", &mut 300) - /// ), - /// } - /// - /// assert_eq!(map[&"c"], 300); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - #[allow(clippy::shadow_unrelated)] - pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - let &mut (ref mut k, ref mut v) = self.table.insert_entry( - hash, - (key, value), - make_hasher::<_, V, S>(self.hash_builder), - ); - (k, v) - } - - /// Set the value of an entry with a custom hasher function. - /// - /// # Examples - /// - /// ``` - /// use core::hash::{BuildHasher, Hash}; - /// use hashbrown::hash_map::{HashMap, RawEntryMut}; - /// - /// fn make_hasher<K, S>(hash_builder: &S) -> impl Fn(&K) -> u64 + '_ - /// where - /// K: Hash + ?Sized, - /// S: BuildHasher, - /// { - /// move |key: &K| { - /// use core::hash::Hasher; - /// let mut state = hash_builder.build_hasher(); - /// key.hash(&mut state); - /// state.finish() - /// } - /// } - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// let key = "a"; - /// let hash_builder = map.hasher().clone(); - /// let hash = make_hasher(&hash_builder)(&key); - /// - /// match map.raw_entry_mut().from_hash(hash, |q| q == &key) { - /// RawEntryMut::Occupied(_) => panic!(), - /// RawEntryMut::Vacant(v) => assert_eq!( - /// v.insert_with_hasher(hash, key, 100, make_hasher(&hash_builder)), - /// (&mut "a", &mut 100) - /// ), - /// } - /// map.extend([("b", 200), ("c", 300), ("d", 400), ("e", 500), ("f", 600)]); - /// assert_eq!(map[&"a"], 100); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert_with_hasher<H>( - self, - hash: u64, - key: K, - value: V, - hasher: H, - ) -> (&'a mut K, &'a mut V) - where - H: Fn(&K) -> u64, - { - let &mut (ref mut k, ref mut v) = self - .table - .insert_entry(hash, (key, value), |x| hasher(&x.0)); - (k, v) - } - - #[cfg_attr(feature = "inline-more", inline)] - fn insert_entry(self, key: K, value: V) -> RawOccupiedEntryMut<'a, K, V, S, A> - where - K: Hash, - S: BuildHasher, - { - let hash = make_insert_hash::<K, S>(self.hash_builder, &key); - let elem = self.table.insert( - hash, - (key, value), - make_hasher::<_, V, S>(self.hash_builder), - ); - RawOccupiedEntryMut { - elem, - table: self.table, - hash_builder: self.hash_builder, - } - } -} - -impl<K, V, S, A: Allocator + Clone> Debug for RawEntryBuilderMut<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawEntryBuilder").finish() - } -} - -impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for RawEntryMut<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(), - RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(), - } - } -} - -impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for RawOccupiedEntryMut<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawOccupiedEntryMut") - .field("key", self.key()) - .field("value", self.get()) - .finish() - } -} - -impl<K, V, S, A: Allocator + Clone> Debug for RawVacantEntryMut<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawVacantEntryMut").finish() - } -} - -impl<K, V, S, A: Allocator + Clone> Debug for RawEntryBuilder<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawEntryBuilder").finish() - } -} - -/// A view into a single entry in a map, which may either be vacant or occupied. -/// -/// This `enum` is constructed from the [`entry`] method on [`HashMap`]. -/// -/// [`HashMap`]: struct.HashMap.html -/// [`entry`]: struct.HashMap.html#method.entry -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{Entry, HashMap, OccupiedEntry}; -/// -/// let mut map = HashMap::new(); -/// map.extend([("a", 10), ("b", 20), ("c", 30)]); -/// assert_eq!(map.len(), 3); -/// -/// // Existing key (insert) -/// let entry: Entry<_, _, _> = map.entry("a"); -/// let _raw_o: OccupiedEntry<_, _, _> = entry.insert(1); -/// assert_eq!(map.len(), 3); -/// // Nonexistent key (insert) -/// map.entry("d").insert(4); -/// -/// // Existing key (or_insert) -/// let v = map.entry("b").or_insert(2); -/// assert_eq!(std::mem::replace(v, 2), 20); -/// // Nonexistent key (or_insert) -/// map.entry("e").or_insert(5); -/// -/// // Existing key (or_insert_with) -/// let v = map.entry("c").or_insert_with(|| 3); -/// assert_eq!(std::mem::replace(v, 3), 30); -/// // Nonexistent key (or_insert_with) -/// map.entry("f").or_insert_with(|| 6); -/// -/// println!("Our HashMap: {:?}", map); -/// -/// let mut vec: Vec<_> = map.iter().map(|(&k, &v)| (k, v)).collect(); -/// // The `Iter` iterator produces items in arbitrary order, so the -/// // items must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, [("a", 1), ("b", 2), ("c", 3), ("d", 4), ("e", 5), ("f", 6)]); -/// ``` -pub enum Entry<'a, K, V, S, A = Global> -where - A: Allocator + Clone, -{ - /// An occupied entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// let mut map: HashMap<_, _> = [("a", 100), ("b", 200)].into(); - /// - /// match map.entry("a") { - /// Entry::Vacant(_) => unreachable!(), - /// Entry::Occupied(_) => { } - /// } - /// ``` - Occupied(OccupiedEntry<'a, K, V, S, A>), - - /// A vacant entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// let mut map: HashMap<&str, i32> = HashMap::new(); - /// - /// match map.entry("a") { - /// Entry::Occupied(_) => unreachable!(), - /// Entry::Vacant(_) => { } - /// } - /// ``` - Vacant(VacantEntry<'a, K, V, S, A>), -} - -impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for Entry<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), - Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), - } - } -} - -/// A view into an occupied entry in a `HashMap`. -/// It is part of the [`Entry`] enum. -/// -/// [`Entry`]: enum.Entry.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{Entry, HashMap, OccupiedEntry}; -/// -/// let mut map = HashMap::new(); -/// map.extend([("a", 10), ("b", 20), ("c", 30)]); -/// -/// let _entry_o: OccupiedEntry<_, _, _> = map.entry("a").insert(100); -/// assert_eq!(map.len(), 3); -/// -/// // Existing key (insert and update) -/// match map.entry("a") { -/// Entry::Vacant(_) => unreachable!(), -/// Entry::Occupied(mut view) => { -/// assert_eq!(view.get(), &100); -/// let v = view.get_mut(); -/// *v *= 10; -/// assert_eq!(view.insert(1111), 1000); -/// } -/// } -/// -/// assert_eq!(map[&"a"], 1111); -/// assert_eq!(map.len(), 3); -/// -/// // Existing key (take) -/// match map.entry("c") { -/// Entry::Vacant(_) => unreachable!(), -/// Entry::Occupied(view) => { -/// assert_eq!(view.remove_entry(), ("c", 30)); -/// } -/// } -/// assert_eq!(map.get(&"c"), None); -/// assert_eq!(map.len(), 2); -/// ``` -pub struct OccupiedEntry<'a, K, V, S, A: Allocator + Clone = Global> { - hash: u64, - key: Option<K>, - elem: Bucket<(K, V)>, - table: &'a mut HashMap<K, V, S, A>, -} - -unsafe impl<K, V, S, A> Send for OccupiedEntry<'_, K, V, S, A> -where - K: Send, - V: Send, - S: Send, - A: Send + Allocator + Clone, -{ -} -unsafe impl<K, V, S, A> Sync for OccupiedEntry<'_, K, V, S, A> -where - K: Sync, - V: Sync, - S: Sync, - A: Sync + Allocator + Clone, -{ -} - -impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for OccupiedEntry<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OccupiedEntry") - .field("key", self.key()) - .field("value", self.get()) - .finish() - } -} - -/// A view into a vacant entry in a `HashMap`. -/// It is part of the [`Entry`] enum. -/// -/// [`Entry`]: enum.Entry.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{Entry, HashMap, VacantEntry}; -/// -/// let mut map = HashMap::<&str, i32>::new(); -/// -/// let entry_v: VacantEntry<_, _, _> = match map.entry("a") { -/// Entry::Vacant(view) => view, -/// Entry::Occupied(_) => unreachable!(), -/// }; -/// entry_v.insert(10); -/// assert!(map[&"a"] == 10 && map.len() == 1); -/// -/// // Nonexistent key (insert and update) -/// match map.entry("b") { -/// Entry::Occupied(_) => unreachable!(), -/// Entry::Vacant(view) => { -/// let value = view.insert(2); -/// assert_eq!(*value, 2); -/// *value = 20; -/// } -/// } -/// assert!(map[&"b"] == 20 && map.len() == 2); -/// ``` -pub struct VacantEntry<'a, K, V, S, A: Allocator + Clone = Global> { - hash: u64, - key: K, - table: &'a mut HashMap<K, V, S, A>, -} - -impl<K: Debug, V, S, A: Allocator + Clone> Debug for VacantEntry<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("VacantEntry").field(self.key()).finish() - } -} - -/// A view into a single entry in a map, which may either be vacant or occupied, -/// with any borrowed form of the map's key type. -/// -/// -/// This `enum` is constructed from the [`entry_ref`] method on [`HashMap`]. -/// -/// [`Hash`] and [`Eq`] on the borrowed form of the map's key type *must* match those -/// for the key type. It also require that key may be constructed from the borrowed -/// form through the [`From`] trait. -/// -/// [`HashMap`]: struct.HashMap.html -/// [`entry_ref`]: struct.HashMap.html#method.entry_ref -/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html -/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html -/// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{EntryRef, HashMap, OccupiedEntryRef}; -/// -/// let mut map = HashMap::new(); -/// map.extend([("a".to_owned(), 10), ("b".into(), 20), ("c".into(), 30)]); -/// assert_eq!(map.len(), 3); -/// -/// // Existing key (insert) -/// let key = String::from("a"); -/// let entry: EntryRef<_, _, _, _> = map.entry_ref(&key); -/// let _raw_o: OccupiedEntryRef<_, _, _, _> = entry.insert(1); -/// assert_eq!(map.len(), 3); -/// // Nonexistent key (insert) -/// map.entry_ref("d").insert(4); -/// -/// // Existing key (or_insert) -/// let v = map.entry_ref("b").or_insert(2); -/// assert_eq!(std::mem::replace(v, 2), 20); -/// // Nonexistent key (or_insert) -/// map.entry_ref("e").or_insert(5); -/// -/// // Existing key (or_insert_with) -/// let v = map.entry_ref("c").or_insert_with(|| 3); -/// assert_eq!(std::mem::replace(v, 3), 30); -/// // Nonexistent key (or_insert_with) -/// map.entry_ref("f").or_insert_with(|| 6); -/// -/// println!("Our HashMap: {:?}", map); -/// -/// for (key, value) in ["a", "b", "c", "d", "e", "f"].into_iter().zip(1..=6) { -/// assert_eq!(map[key], value) -/// } -/// assert_eq!(map.len(), 6); -/// ``` -pub enum EntryRef<'a, 'b, K, Q: ?Sized, V, S, A = Global> -where - A: Allocator + Clone, -{ - /// An occupied entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{EntryRef, HashMap}; - /// let mut map: HashMap<_, _> = [("a".to_owned(), 100), ("b".into(), 200)].into(); - /// - /// match map.entry_ref("a") { - /// EntryRef::Vacant(_) => unreachable!(), - /// EntryRef::Occupied(_) => { } - /// } - /// ``` - Occupied(OccupiedEntryRef<'a, 'b, K, Q, V, S, A>), - - /// A vacant entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{EntryRef, HashMap}; - /// let mut map: HashMap<String, i32> = HashMap::new(); - /// - /// match map.entry_ref("a") { - /// EntryRef::Occupied(_) => unreachable!(), - /// EntryRef::Vacant(_) => { } - /// } - /// ``` - Vacant(VacantEntryRef<'a, 'b, K, Q, V, S, A>), -} - -impl<K: Borrow<Q>, Q: ?Sized + Debug, V: Debug, S, A: Allocator + Clone> Debug - for EntryRef<'_, '_, K, Q, V, S, A> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - EntryRef::Vacant(ref v) => f.debug_tuple("EntryRef").field(v).finish(), - EntryRef::Occupied(ref o) => f.debug_tuple("EntryRef").field(o).finish(), - } - } -} - -enum KeyOrRef<'a, K, Q: ?Sized> { - Borrowed(&'a Q), - Owned(K), -} - -impl<'a, K, Q: ?Sized> KeyOrRef<'a, K, Q> { - fn into_owned(self) -> K - where - K: From<&'a Q>, - { - match self { - Self::Borrowed(borrowed) => borrowed.into(), - Self::Owned(owned) => owned, - } - } -} - -impl<'a, K: Borrow<Q>, Q: ?Sized> AsRef<Q> for KeyOrRef<'a, K, Q> { - fn as_ref(&self) -> &Q { - match self { - Self::Borrowed(borrowed) => borrowed, - Self::Owned(owned) => owned.borrow(), - } - } -} - -/// A view into an occupied entry in a `HashMap`. -/// It is part of the [`EntryRef`] enum. -/// -/// [`EntryRef`]: enum.EntryRef.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{EntryRef, HashMap, OccupiedEntryRef}; -/// -/// let mut map = HashMap::new(); -/// map.extend([("a".to_owned(), 10), ("b".into(), 20), ("c".into(), 30)]); -/// -/// let key = String::from("a"); -/// let _entry_o: OccupiedEntryRef<_, _, _, _> = map.entry_ref(&key).insert(100); -/// assert_eq!(map.len(), 3); -/// -/// // Existing key (insert and update) -/// match map.entry_ref("a") { -/// EntryRef::Vacant(_) => unreachable!(), -/// EntryRef::Occupied(mut view) => { -/// assert_eq!(view.get(), &100); -/// let v = view.get_mut(); -/// *v *= 10; -/// assert_eq!(view.insert(1111), 1000); -/// } -/// } -/// -/// assert_eq!(map["a"], 1111); -/// assert_eq!(map.len(), 3); -/// -/// // Existing key (take) -/// match map.entry_ref("c") { -/// EntryRef::Vacant(_) => unreachable!(), -/// EntryRef::Occupied(view) => { -/// assert_eq!(view.remove_entry(), ("c".to_owned(), 30)); -/// } -/// } -/// assert_eq!(map.get("c"), None); -/// assert_eq!(map.len(), 2); -/// ``` -pub struct OccupiedEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone = Global> { - hash: u64, - key: Option<KeyOrRef<'b, K, Q>>, - elem: Bucket<(K, V)>, - table: &'a mut HashMap<K, V, S, A>, -} - -unsafe impl<'a, 'b, K, Q, V, S, A> Send for OccupiedEntryRef<'a, 'b, K, Q, V, S, A> -where - K: Send, - Q: Sync + ?Sized, - V: Send, - S: Send, - A: Send + Allocator + Clone, -{ -} -unsafe impl<'a, 'b, K, Q, V, S, A> Sync for OccupiedEntryRef<'a, 'b, K, Q, V, S, A> -where - K: Sync, - Q: Sync + ?Sized, - V: Sync, - S: Sync, - A: Sync + Allocator + Clone, -{ -} - -impl<K: Borrow<Q>, Q: ?Sized + Debug, V: Debug, S, A: Allocator + Clone> Debug - for OccupiedEntryRef<'_, '_, K, Q, V, S, A> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OccupiedEntryRef") - .field("key", &self.key()) - .field("value", &self.get()) - .finish() - } -} - -/// A view into a vacant entry in a `HashMap`. -/// It is part of the [`EntryRef`] enum. -/// -/// [`EntryRef`]: enum.EntryRef.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{EntryRef, HashMap, VacantEntryRef}; -/// -/// let mut map = HashMap::<String, i32>::new(); -/// -/// let entry_v: VacantEntryRef<_, _, _, _> = match map.entry_ref("a") { -/// EntryRef::Vacant(view) => view, -/// EntryRef::Occupied(_) => unreachable!(), -/// }; -/// entry_v.insert(10); -/// assert!(map["a"] == 10 && map.len() == 1); -/// -/// // Nonexistent key (insert and update) -/// match map.entry_ref("b") { -/// EntryRef::Occupied(_) => unreachable!(), -/// EntryRef::Vacant(view) => { -/// let value = view.insert(2); -/// assert_eq!(*value, 2); -/// *value = 20; -/// } -/// } -/// assert!(map["b"] == 20 && map.len() == 2); -/// ``` -pub struct VacantEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone = Global> { - hash: u64, - key: KeyOrRef<'b, K, Q>, - table: &'a mut HashMap<K, V, S, A>, -} - -impl<K: Borrow<Q>, Q: ?Sized + Debug, V, S, A: Allocator + Clone> Debug - for VacantEntryRef<'_, '_, K, Q, V, S, A> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("VacantEntryRef").field(&self.key()).finish() - } -} - -/// The error returned by [`try_insert`](HashMap::try_insert) when the key already exists. -/// -/// Contains the occupied entry, and the value that was not inserted. -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_map::{HashMap, OccupiedError}; -/// -/// let mut map: HashMap<_, _> = [("a", 10), ("b", 20)].into(); -/// -/// // try_insert method returns mutable reference to the value if keys are vacant, -/// // but if the map did have key present, nothing is updated, and the provided -/// // value is returned inside `Err(_)` variant -/// match map.try_insert("a", 100) { -/// Err(OccupiedError { mut entry, value }) => { -/// assert_eq!(entry.key(), &"a"); -/// assert_eq!(value, 100); -/// assert_eq!(entry.insert(100), 10) -/// } -/// _ => unreachable!(), -/// } -/// assert_eq!(map[&"a"], 100); -/// ``` -pub struct OccupiedError<'a, K, V, S, A: Allocator + Clone = Global> { - /// The entry in the map that was already occupied. - pub entry: OccupiedEntry<'a, K, V, S, A>, - /// The value which was not inserted, because the entry was already occupied. - pub value: V, -} - -impl<K: Debug, V: Debug, S, A: Allocator + Clone> Debug for OccupiedError<'_, K, V, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OccupiedError") - .field("key", self.entry.key()) - .field("old_value", self.entry.get()) - .field("new_value", &self.value) - .finish() - } -} - -impl<'a, K: Debug, V: Debug, S, A: Allocator + Clone> fmt::Display - for OccupiedError<'a, K, V, S, A> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "failed to insert {:?}, key {:?} already exists with value {:?}", - self.value, - self.entry.key(), - self.entry.get(), - ) - } -} - -impl<'a, K, V, S, A: Allocator + Clone> IntoIterator for &'a HashMap<K, V, S, A> { - type Item = (&'a K, &'a V); - type IntoIter = Iter<'a, K, V>; - - /// Creates an iterator over the entries of a `HashMap` in arbitrary order. - /// The iterator element type is `(&'a K, &'a V)`. - /// - /// Return the same `Iter` struct as by the [`iter`] method on [`HashMap`]. - /// - /// [`iter`]: struct.HashMap.html#method.iter - /// [`HashMap`]: struct.HashMap.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let map_one: HashMap<_, _> = [(1, "a"), (2, "b"), (3, "c")].into(); - /// let mut map_two = HashMap::new(); - /// - /// for (key, value) in &map_one { - /// println!("Key: {}, Value: {}", key, value); - /// map_two.insert_unique_unchecked(*key, *value); - /// } - /// - /// assert_eq!(map_one, map_two); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn into_iter(self) -> Iter<'a, K, V> { - self.iter() - } -} - -impl<'a, K, V, S, A: Allocator + Clone> IntoIterator for &'a mut HashMap<K, V, S, A> { - type Item = (&'a K, &'a mut V); - type IntoIter = IterMut<'a, K, V>; - - /// Creates an iterator over the entries of a `HashMap` in arbitrary order - /// with mutable references to the values. The iterator element type is - /// `(&'a K, &'a mut V)`. - /// - /// Return the same `IterMut` struct as by the [`iter_mut`] method on - /// [`HashMap`]. - /// - /// [`iter_mut`]: struct.HashMap.html#method.iter_mut - /// [`HashMap`]: struct.HashMap.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// let mut map: HashMap<_, _> = [("a", 1), ("b", 2), ("c", 3)].into(); - /// - /// for (key, value) in &mut map { - /// println!("Key: {}, Value: {}", key, value); - /// *value *= 2; - /// } - /// - /// let mut vec = map.iter().collect::<Vec<_>>(); - /// // The `Iter` iterator produces items in arbitrary order, so the - /// // items must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [(&"a", &2), (&"b", &4), (&"c", &6)]); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn into_iter(self) -> IterMut<'a, K, V> { - self.iter_mut() - } -} - -impl<K, V, S, A: Allocator + Clone> IntoIterator for HashMap<K, V, S, A> { - type Item = (K, V); - type IntoIter = IntoIter<K, V, A>; - - /// Creates a consuming iterator, that is, one that moves each key-value - /// pair out of the map in arbitrary order. The map cannot be used after - /// calling this. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let map: HashMap<_, _> = [("a", 1), ("b", 2), ("c", 3)].into(); - /// - /// // Not possible with .iter() - /// let mut vec: Vec<(&str, i32)> = map.into_iter().collect(); - /// // The `IntoIter` iterator produces items in arbitrary order, so - /// // the items must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [("a", 1), ("b", 2), ("c", 3)]); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn into_iter(self) -> IntoIter<K, V, A> { - IntoIter { - inner: self.table.into_iter(), - } - } -} - -impl<'a, K, V> Iterator for Iter<'a, K, V> { - type Item = (&'a K, &'a V); - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<(&'a K, &'a V)> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.inner.next() { - Some(x) => unsafe { - let r = x.as_ref(); - Some((&r.0, &r.1)) - }, - None => None, - } - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} -impl<K, V> ExactSizeIterator for Iter<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.inner.len() - } -} - -impl<K, V> FusedIterator for Iter<'_, K, V> {} - -impl<'a, K, V> Iterator for IterMut<'a, K, V> { - type Item = (&'a K, &'a mut V); - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<(&'a K, &'a mut V)> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.inner.next() { - Some(x) => unsafe { - let r = x.as_mut(); - Some((&r.0, &mut r.1)) - }, - None => None, - } - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} -impl<K, V> ExactSizeIterator for IterMut<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.inner.len() - } -} -impl<K, V> FusedIterator for IterMut<'_, K, V> {} - -impl<K, V> fmt::Debug for IterMut<'_, K, V> -where - K: fmt::Debug, - V: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -impl<K, V, A: Allocator + Clone> Iterator for IntoIter<K, V, A> { - type Item = (K, V); - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<(K, V)> { - self.inner.next() - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} -impl<K, V, A: Allocator + Clone> ExactSizeIterator for IntoIter<K, V, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.inner.len() - } -} -impl<K, V, A: Allocator + Clone> FusedIterator for IntoIter<K, V, A> {} - -impl<K: Debug, V: Debug, A: Allocator + Clone> fmt::Debug for IntoIter<K, V, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -impl<'a, K, V> Iterator for Keys<'a, K, V> { - type Item = &'a K; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<&'a K> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.inner.next() { - Some((k, _)) => Some(k), - None => None, - } - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} -impl<K, V> ExactSizeIterator for Keys<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.inner.len() - } -} -impl<K, V> FusedIterator for Keys<'_, K, V> {} - -impl<'a, K, V> Iterator for Values<'a, K, V> { - type Item = &'a V; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<&'a V> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.inner.next() { - Some((_, v)) => Some(v), - None => None, - } - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} -impl<K, V> ExactSizeIterator for Values<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.inner.len() - } -} -impl<K, V> FusedIterator for Values<'_, K, V> {} - -impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { - type Item = &'a mut V; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<&'a mut V> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.inner.next() { - Some((_, v)) => Some(v), - None => None, - } - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} -impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.inner.len() - } -} -impl<K, V> FusedIterator for ValuesMut<'_, K, V> {} - -impl<K, V: Debug> fmt::Debug for ValuesMut<'_, K, V> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list() - .entries(self.inner.iter().map(|(_, val)| val)) - .finish() - } -} - -impl<'a, K, V, A: Allocator + Clone> Iterator for Drain<'a, K, V, A> { - type Item = (K, V); - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<(K, V)> { - self.inner.next() - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.inner.size_hint() - } -} -impl<K, V, A: Allocator + Clone> ExactSizeIterator for Drain<'_, K, V, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.inner.len() - } -} -impl<K, V, A: Allocator + Clone> FusedIterator for Drain<'_, K, V, A> {} - -impl<K, V, A> fmt::Debug for Drain<'_, K, V, A> -where - K: fmt::Debug, - V: fmt::Debug, - A: Allocator + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -impl<'a, K, V, S, A: Allocator + Clone> Entry<'a, K, V, S, A> { - /// Sets the value of the entry, and returns an OccupiedEntry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// let entry = map.entry("horseyland").insert(37); - /// - /// assert_eq!(entry.key(), &"horseyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V, S, A> - where - K: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(mut entry) => { - entry.insert(value); - entry - } - Entry::Vacant(entry) => entry.insert_entry(value), - } - } - - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// // nonexistent key - /// map.entry("poneyland").or_insert(3); - /// assert_eq!(map["poneyland"], 3); - /// - /// // existing key - /// *map.entry("poneyland").or_insert(10) *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert(self, default: V) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => entry.insert(default), - } - } - - /// Ensures a value is in the entry by inserting the result of the default function if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// // nonexistent key - /// map.entry("poneyland").or_insert_with(|| 3); - /// assert_eq!(map["poneyland"], 3); - /// - /// // existing key - /// *map.entry("poneyland").or_insert_with(|| 10) *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => entry.insert(default()), - } - } - - /// Ensures a value is in the entry by inserting, if empty, the result of the default function. - /// This method allows for generating key-derived values for insertion by providing the default - /// function a reference to the key that was moved during the `.entry(key)` method call. - /// - /// The reference to the moved key is provided so that cloning or copying the key is - /// unnecessary, unlike with `.or_insert_with(|| ... )`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, usize> = HashMap::new(); - /// - /// // nonexistent key - /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count()); - /// assert_eq!(map["poneyland"], 9); - /// - /// // existing key - /// *map.entry("poneyland").or_insert_with_key(|key| key.chars().count() * 10) *= 2; - /// assert_eq!(map["poneyland"], 18); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => { - let value = default(entry.key()); - entry.insert(value) - } - } - } - - /// Returns a reference to this entry's key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(3); - /// // existing key - /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); - /// // nonexistent key - /// assert_eq!(map.entry("horseland").key(), &"horseland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &K { - match *self { - Entry::Occupied(ref entry) => entry.key(), - Entry::Vacant(ref entry) => entry.key(), - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.entry("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 42); - /// - /// map.entry("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 43); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn and_modify<F>(self, f: F) -> Self - where - F: FnOnce(&mut V), - { - match self { - Entry::Occupied(mut entry) => { - f(entry.get_mut()); - Entry::Occupied(entry) - } - Entry::Vacant(entry) => Entry::Vacant(entry), - } - } - - /// Provides shared access to the key and owned access to the value of - /// an occupied entry and allows to replace or remove it based on the - /// value of the returned option. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// let entry = map - /// .entry("poneyland") - /// .and_replace_entry_with(|_k, _v| panic!()); - /// - /// match entry { - /// Entry::Vacant(e) => { - /// assert_eq!(e.key(), &"poneyland"); - /// } - /// Entry::Occupied(_) => panic!(), - /// } - /// - /// map.insert("poneyland", 42); - /// - /// let entry = map - /// .entry("poneyland") - /// .and_replace_entry_with(|k, v| { - /// assert_eq!(k, &"poneyland"); - /// assert_eq!(v, 42); - /// Some(v + 1) - /// }); - /// - /// match entry { - /// Entry::Occupied(e) => { - /// assert_eq!(e.key(), &"poneyland"); - /// assert_eq!(e.get(), &43); - /// } - /// Entry::Vacant(_) => panic!(), - /// } - /// - /// assert_eq!(map["poneyland"], 43); - /// - /// let entry = map - /// .entry("poneyland") - /// .and_replace_entry_with(|_k, _v| None); - /// - /// match entry { - /// Entry::Vacant(e) => assert_eq!(e.key(), &"poneyland"), - /// Entry::Occupied(_) => panic!(), - /// } - /// - /// assert!(!map.contains_key("poneyland")); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn and_replace_entry_with<F>(self, f: F) -> Self - where - F: FnOnce(&K, V) -> Option<V>, - { - match self { - Entry::Occupied(entry) => entry.replace_entry_with(f), - Entry::Vacant(_) => self, - } - } -} - -impl<'a, K, V: Default, S, A: Allocator + Clone> Entry<'a, K, V, S, A> { - /// Ensures a value is in the entry by inserting the default value if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, Option<u32>> = HashMap::new(); - /// - /// // nonexistent key - /// map.entry("poneyland").or_default(); - /// assert_eq!(map["poneyland"], None); - /// - /// map.insert("horseland", Some(3)); - /// - /// // existing key - /// assert_eq!(map.entry("horseland").or_default(), &mut Some(3)); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_default(self) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => entry.insert(Default::default()), - } - } -} - -impl<'a, K, V, S, A: Allocator + Clone> OccupiedEntry<'a, K, V, S, A> { - /// Gets a reference to the key in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// match map.entry("poneyland") { - /// Entry::Vacant(_) => panic!(), - /// Entry::Occupied(entry) => assert_eq!(entry.key(), &"poneyland"), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &K { - unsafe { &self.elem.as_ref().0 } - } - - /// Take the ownership of the key and value from the map. - /// Keeps the allocated memory for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// // The map is empty - /// assert!(map.is_empty() && map.capacity() == 0); - /// - /// map.entry("poneyland").or_insert(12); - /// - /// if let Entry::Occupied(o) = map.entry("poneyland") { - /// // We delete the entry from the map. - /// assert_eq!(o.remove_entry(), ("poneyland", 12)); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// // Now map hold none elements - /// assert!(map.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove_entry(self) -> (K, V) { - unsafe { self.table.table.remove(self.elem) } - } - - /// Gets a reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// match map.entry("poneyland") { - /// Entry::Vacant(_) => panic!(), - /// Entry::Occupied(entry) => assert_eq!(entry.get(), &12), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get(&self) -> &V { - unsafe { &self.elem.as_ref().1 } - } - - /// Gets a mutable reference to the value in the entry. - /// - /// If you need a reference to the `OccupiedEntry` which may outlive the - /// destruction of the `Entry` value, see [`into_mut`]. - /// - /// [`into_mut`]: #method.into_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// if let Entry::Occupied(mut o) = map.entry("poneyland") { - /// *o.get_mut() += 10; - /// assert_eq!(*o.get(), 22); - /// - /// // We can use the same Entry multiple times. - /// *o.get_mut() += 2; - /// } - /// - /// assert_eq!(map["poneyland"], 24); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_mut(&mut self) -> &mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Converts the OccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself. - /// - /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`]. - /// - /// [`get_mut`]: #method.get_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// - /// let value: &mut u32; - /// match map.entry("poneyland") { - /// Entry::Occupied(entry) => value = entry.into_mut(), - /// Entry::Vacant(_) => panic!(), - /// } - /// *value += 10; - /// - /// assert_eq!(map["poneyland"], 22); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_mut(self) -> &'a mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Sets the value of the entry, and returns the entry's old value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.entry("poneyland").or_insert(12); - /// - /// if let Entry::Occupied(mut o) = map.entry("poneyland") { - /// assert_eq!(o.insert(15), 12); - /// } - /// - /// assert_eq!(map["poneyland"], 15); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(&mut self, value: V) -> V { - mem::replace(self.get_mut(), value) - } - - /// Takes the value out of the entry, and returns it. - /// Keeps the allocated memory for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// // The map is empty - /// assert!(map.is_empty() && map.capacity() == 0); - /// - /// map.entry("poneyland").or_insert(12); - /// - /// if let Entry::Occupied(o) = map.entry("poneyland") { - /// assert_eq!(o.remove(), 12); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// // Now map hold none elements - /// assert!(map.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove(self) -> V { - self.remove_entry().1 - } - - /// Replaces the entry, returning the old key and value. The new key in the hash map will be - /// the key used to create this entry. - /// - /// # Panics - /// - /// Will panic if this OccupiedEntry was created through [`Entry::insert`]. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap<Rc<String>, u32> = HashMap::new(); - /// let key_one = Rc::new("Stringthing".to_string()); - /// let key_two = Rc::new("Stringthing".to_string()); - /// - /// map.insert(key_one.clone(), 15); - /// assert!(Rc::strong_count(&key_one) == 2 && Rc::strong_count(&key_two) == 1); - /// - /// match map.entry(key_two.clone()) { - /// Entry::Occupied(entry) => { - /// let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16); - /// assert!(Rc::ptr_eq(&key_one, &old_key) && old_value == 15); - /// } - /// Entry::Vacant(_) => panic!(), - /// } - /// - /// assert!(Rc::strong_count(&key_one) == 1 && Rc::strong_count(&key_two) == 2); - /// assert_eq!(map[&"Stringthing".to_owned()], 16); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_entry(self, value: V) -> (K, V) { - let entry = unsafe { self.elem.as_mut() }; - - let old_key = mem::replace(&mut entry.0, self.key.unwrap()); - let old_value = mem::replace(&mut entry.1, value); - - (old_key, old_value) - } - - /// Replaces the key in the hash map with the key used to create this entry. - /// - /// # Panics - /// - /// Will panic if this OccupiedEntry was created through [`Entry::insert`]. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap<Rc<String>, usize> = HashMap::with_capacity(6); - /// let mut keys_one: Vec<Rc<String>> = Vec::with_capacity(6); - /// let mut keys_two: Vec<Rc<String>> = Vec::with_capacity(6); - /// - /// for (value, key) in ["a", "b", "c", "d", "e", "f"].into_iter().enumerate() { - /// let rc_key = Rc::new(key.to_owned()); - /// keys_one.push(rc_key.clone()); - /// map.insert(rc_key.clone(), value); - /// keys_two.push(Rc::new(key.to_owned())); - /// } - /// - /// assert!( - /// keys_one.iter().all(|key| Rc::strong_count(key) == 2) - /// && keys_two.iter().all(|key| Rc::strong_count(key) == 1) - /// ); - /// - /// reclaim_memory(&mut map, &keys_two); - /// - /// assert!( - /// keys_one.iter().all(|key| Rc::strong_count(key) == 1) - /// && keys_two.iter().all(|key| Rc::strong_count(key) == 2) - /// ); - /// - /// fn reclaim_memory(map: &mut HashMap<Rc<String>, usize>, keys: &[Rc<String>]) { - /// for key in keys { - /// if let Entry::Occupied(entry) = map.entry(key.clone()) { - /// // Replaces the entry's key with our version of it in `keys`. - /// entry.replace_key(); - /// } - /// } - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_key(self) -> K { - let entry = unsafe { self.elem.as_mut() }; - mem::replace(&mut entry.0, self.key.unwrap()) - } - - /// Provides shared access to the key and owned access to the value of - /// the entry and allows to replace or remove it based on the - /// value of the returned option. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.insert("poneyland", 42); - /// - /// let entry = match map.entry("poneyland") { - /// Entry::Occupied(e) => { - /// e.replace_entry_with(|k, v| { - /// assert_eq!(k, &"poneyland"); - /// assert_eq!(v, 42); - /// Some(v + 1) - /// }) - /// } - /// Entry::Vacant(_) => panic!(), - /// }; - /// - /// match entry { - /// Entry::Occupied(e) => { - /// assert_eq!(e.key(), &"poneyland"); - /// assert_eq!(e.get(), &43); - /// } - /// Entry::Vacant(_) => panic!(), - /// } - /// - /// assert_eq!(map["poneyland"], 43); - /// - /// let entry = match map.entry("poneyland") { - /// Entry::Occupied(e) => e.replace_entry_with(|_k, _v| None), - /// Entry::Vacant(_) => panic!(), - /// }; - /// - /// match entry { - /// Entry::Vacant(e) => { - /// assert_eq!(e.key(), &"poneyland"); - /// } - /// Entry::Occupied(_) => panic!(), - /// } - /// - /// assert!(!map.contains_key("poneyland")); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_entry_with<F>(self, f: F) -> Entry<'a, K, V, S, A> - where - F: FnOnce(&K, V) -> Option<V>, - { - unsafe { - let mut spare_key = None; - - self.table - .table - .replace_bucket_with(self.elem.clone(), |(key, value)| { - if let Some(new_value) = f(&key, value) { - Some((key, new_value)) - } else { - spare_key = Some(key); - None - } - }); - - if let Some(key) = spare_key { - Entry::Vacant(VacantEntry { - hash: self.hash, - key, - table: self.table, - }) - } else { - Entry::Occupied(self) - } - } - } -} - -impl<'a, K, V, S, A: Allocator + Clone> VacantEntry<'a, K, V, S, A> { - /// Gets a reference to the key that would be used when inserting a value - /// through the `VacantEntry`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &K { - &self.key - } - - /// Take ownership of the key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{Entry, HashMap}; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// match map.entry("poneyland") { - /// Entry::Occupied(_) => panic!(), - /// Entry::Vacant(v) => assert_eq!(v.into_key(), "poneyland"), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_key(self) -> K { - self.key - } - - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::Entry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// if let Entry::Vacant(o) = map.entry("poneyland") { - /// o.insert(37); - /// } - /// assert_eq!(map["poneyland"], 37); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, value: V) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - let table = &mut self.table.table; - let entry = table.insert_entry( - self.hash, - (self.key, value), - make_hasher::<_, V, S>(&self.table.hash_builder), - ); - &mut entry.1 - } - - #[cfg_attr(feature = "inline-more", inline)] - pub(crate) fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S, A> - where - K: Hash, - S: BuildHasher, - { - let elem = self.table.table.insert( - self.hash, - (self.key, value), - make_hasher::<_, V, S>(&self.table.hash_builder), - ); - OccupiedEntry { - hash: self.hash, - key: None, - elem, - table: self.table, - } - } -} - -impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V, S, A> { - /// Sets the value of the entry, and returns an OccupiedEntryRef. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// let entry = map.entry_ref("horseyland").insert(37); - /// - /// assert_eq!(entry.key(), "horseyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, value: V) -> OccupiedEntryRef<'a, 'b, K, Q, V, S, A> - where - K: Hash + From<&'b Q>, - S: BuildHasher, - { - match self { - EntryRef::Occupied(mut entry) => { - entry.insert(value); - entry - } - EntryRef::Vacant(entry) => entry.insert_entry(value), - } - } - - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// - /// // nonexistent key - /// map.entry_ref("poneyland").or_insert(3); - /// assert_eq!(map["poneyland"], 3); - /// - /// // existing key - /// *map.entry_ref("poneyland").or_insert(10) *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert(self, default: V) -> &'a mut V - where - K: Hash + From<&'b Q>, - S: BuildHasher, - { - match self { - EntryRef::Occupied(entry) => entry.into_mut(), - EntryRef::Vacant(entry) => entry.insert(default), - } - } - - /// Ensures a value is in the entry by inserting the result of the default function if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// - /// // nonexistent key - /// map.entry_ref("poneyland").or_insert_with(|| 3); - /// assert_eq!(map["poneyland"], 3); - /// - /// // existing key - /// *map.entry_ref("poneyland").or_insert_with(|| 10) *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V - where - K: Hash + From<&'b Q>, - S: BuildHasher, - { - match self { - EntryRef::Occupied(entry) => entry.into_mut(), - EntryRef::Vacant(entry) => entry.insert(default()), - } - } - - /// Ensures a value is in the entry by inserting, if empty, the result of the default function. - /// This method allows for generating key-derived values for insertion by providing the default - /// function an access to the borrower form of the key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<String, usize> = HashMap::new(); - /// - /// // nonexistent key - /// map.entry_ref("poneyland").or_insert_with_key(|key| key.chars().count()); - /// assert_eq!(map["poneyland"], 9); - /// - /// // existing key - /// *map.entry_ref("poneyland").or_insert_with_key(|key| key.chars().count() * 10) *= 2; - /// assert_eq!(map["poneyland"], 18); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert_with_key<F: FnOnce(&Q) -> V>(self, default: F) -> &'a mut V - where - K: Hash + Borrow<Q> + From<&'b Q>, - S: BuildHasher, - { - match self { - EntryRef::Occupied(entry) => entry.into_mut(), - EntryRef::Vacant(entry) => { - let value = default(entry.key.as_ref()); - entry.insert(value) - } - } - } - - /// Returns a reference to this entry's key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// map.entry_ref("poneyland").or_insert(3); - /// // existing key - /// assert_eq!(map.entry_ref("poneyland").key(), "poneyland"); - /// // nonexistent key - /// assert_eq!(map.entry_ref("horseland").key(), "horseland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &Q - where - K: Borrow<Q>, - { - match *self { - EntryRef::Occupied(ref entry) => entry.key(), - EntryRef::Vacant(ref entry) => entry.key(), - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// - /// map.entry_ref("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 42); - /// - /// map.entry_ref("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 43); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn and_modify<F>(self, f: F) -> Self - where - F: FnOnce(&mut V), - { - match self { - EntryRef::Occupied(mut entry) => { - f(entry.get_mut()); - EntryRef::Occupied(entry) - } - EntryRef::Vacant(entry) => EntryRef::Vacant(entry), - } - } - - /// Provides shared access to the key and owned access to the value of - /// an occupied entry and allows to replace or remove it based on the - /// value of the returned option. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::EntryRef; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// - /// let entry = map - /// .entry_ref("poneyland") - /// .and_replace_entry_with(|_k, _v| panic!()); - /// - /// match entry { - /// EntryRef::Vacant(e) => { - /// assert_eq!(e.key(), "poneyland"); - /// } - /// EntryRef::Occupied(_) => panic!(), - /// } - /// - /// map.insert("poneyland".to_string(), 42); - /// - /// let entry = map - /// .entry_ref("poneyland") - /// .and_replace_entry_with(|k, v| { - /// assert_eq!(k, "poneyland"); - /// assert_eq!(v, 42); - /// Some(v + 1) - /// }); - /// - /// match entry { - /// EntryRef::Occupied(e) => { - /// assert_eq!(e.key(), "poneyland"); - /// assert_eq!(e.get(), &43); - /// } - /// EntryRef::Vacant(_) => panic!(), - /// } - /// - /// assert_eq!(map["poneyland"], 43); - /// - /// let entry = map - /// .entry_ref("poneyland") - /// .and_replace_entry_with(|_k, _v| None); - /// - /// match entry { - /// EntryRef::Vacant(e) => assert_eq!(e.key(), "poneyland"), - /// EntryRef::Occupied(_) => panic!(), - /// } - /// - /// assert!(!map.contains_key("poneyland")); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn and_replace_entry_with<F>(self, f: F) -> Self - where - F: FnOnce(&Q, V) -> Option<V>, - K: Borrow<Q>, - { - match self { - EntryRef::Occupied(entry) => entry.replace_entry_with(f), - EntryRef::Vacant(_) => self, - } - } -} - -impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator + Clone> EntryRef<'a, 'b, K, Q, V, S, A> { - /// Ensures a value is in the entry by inserting the default value if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<String, Option<u32>> = HashMap::new(); - /// - /// // nonexistent key - /// map.entry_ref("poneyland").or_default(); - /// assert_eq!(map["poneyland"], None); - /// - /// map.insert("horseland".to_string(), Some(3)); - /// - /// // existing key - /// assert_eq!(map.entry_ref("horseland").or_default(), &mut Some(3)); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_default(self) -> &'a mut V - where - K: Hash + From<&'b Q>, - S: BuildHasher, - { - match self { - EntryRef::Occupied(entry) => entry.into_mut(), - EntryRef::Vacant(entry) => entry.insert(Default::default()), - } - } -} - -impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> OccupiedEntryRef<'a, 'b, K, Q, V, S, A> { - /// Gets a reference to the key in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{EntryRef, HashMap}; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// map.entry_ref("poneyland").or_insert(12); - /// - /// match map.entry_ref("poneyland") { - /// EntryRef::Vacant(_) => panic!(), - /// EntryRef::Occupied(entry) => assert_eq!(entry.key(), "poneyland"), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &Q - where - K: Borrow<Q>, - { - unsafe { &self.elem.as_ref().0 }.borrow() - } - - /// Take the ownership of the key and value from the map. - /// Keeps the allocated memory for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::EntryRef; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// // The map is empty - /// assert!(map.is_empty() && map.capacity() == 0); - /// - /// map.entry_ref("poneyland").or_insert(12); - /// - /// if let EntryRef::Occupied(o) = map.entry_ref("poneyland") { - /// // We delete the entry from the map. - /// assert_eq!(o.remove_entry(), ("poneyland".to_owned(), 12)); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// // Now map hold none elements but capacity is equal to the old one - /// assert!(map.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove_entry(self) -> (K, V) { - unsafe { self.table.table.remove(self.elem) } - } - - /// Gets a reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::EntryRef; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// map.entry_ref("poneyland").or_insert(12); - /// - /// match map.entry_ref("poneyland") { - /// EntryRef::Vacant(_) => panic!(), - /// EntryRef::Occupied(entry) => assert_eq!(entry.get(), &12), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get(&self) -> &V { - unsafe { &self.elem.as_ref().1 } - } - - /// Gets a mutable reference to the value in the entry. - /// - /// If you need a reference to the `OccupiedEntryRef` which may outlive the - /// destruction of the `EntryRef` value, see [`into_mut`]. - /// - /// [`into_mut`]: #method.into_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::EntryRef; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// map.entry_ref("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// if let EntryRef::Occupied(mut o) = map.entry_ref("poneyland") { - /// *o.get_mut() += 10; - /// assert_eq!(*o.get(), 22); - /// - /// // We can use the same Entry multiple times. - /// *o.get_mut() += 2; - /// } - /// - /// assert_eq!(map["poneyland"], 24); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_mut(&mut self) -> &mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Converts the OccupiedEntryRef into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself. - /// - /// If you need multiple references to the `OccupiedEntryRef`, see [`get_mut`]. - /// - /// [`get_mut`]: #method.get_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{EntryRef, HashMap}; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// map.entry_ref("poneyland").or_insert(12); - /// - /// let value: &mut u32; - /// match map.entry_ref("poneyland") { - /// EntryRef::Occupied(entry) => value = entry.into_mut(), - /// EntryRef::Vacant(_) => panic!(), - /// } - /// *value += 10; - /// - /// assert_eq!(map["poneyland"], 22); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_mut(self) -> &'a mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Sets the value of the entry, and returns the entry's old value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::EntryRef; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// map.entry_ref("poneyland").or_insert(12); - /// - /// if let EntryRef::Occupied(mut o) = map.entry_ref("poneyland") { - /// assert_eq!(o.insert(15), 12); - /// } - /// - /// assert_eq!(map["poneyland"], 15); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(&mut self, value: V) -> V { - mem::replace(self.get_mut(), value) - } - - /// Takes the value out of the entry, and returns it. - /// Keeps the allocated memory for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::EntryRef; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// // The map is empty - /// assert!(map.is_empty() && map.capacity() == 0); - /// - /// map.entry_ref("poneyland").or_insert(12); - /// - /// if let EntryRef::Occupied(o) = map.entry_ref("poneyland") { - /// assert_eq!(o.remove(), 12); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// // Now map hold none elements but capacity is equal to the old one - /// assert!(map.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove(self) -> V { - self.remove_entry().1 - } - - /// Replaces the entry, returning the old key and value. The new key in the hash map will be - /// the key used to create this entry. - /// - /// # Panics - /// - /// Will panic if this OccupiedEntryRef was created through [`EntryRef::insert`]. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{EntryRef, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap<Rc<str>, u32> = HashMap::new(); - /// let key: Rc<str> = Rc::from("Stringthing"); - /// - /// map.insert(key.clone(), 15); - /// assert_eq!(Rc::strong_count(&key), 2); - /// - /// match map.entry_ref("Stringthing") { - /// EntryRef::Occupied(entry) => { - /// let (old_key, old_value): (Rc<str>, u32) = entry.replace_entry(16); - /// assert!(Rc::ptr_eq(&key, &old_key) && old_value == 15); - /// } - /// EntryRef::Vacant(_) => panic!(), - /// } - /// - /// assert_eq!(Rc::strong_count(&key), 1); - /// assert_eq!(map["Stringthing"], 16); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_entry(self, value: V) -> (K, V) - where - K: From<&'b Q>, - { - let entry = unsafe { self.elem.as_mut() }; - - let old_key = mem::replace(&mut entry.0, self.key.unwrap().into_owned()); - let old_value = mem::replace(&mut entry.1, value); - - (old_key, old_value) - } - - /// Replaces the key in the hash map with the key used to create this entry. - /// - /// # Panics - /// - /// Will panic if this OccupiedEntryRef was created through [`EntryRef::insert`]. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{EntryRef, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap<Rc<str>, usize> = HashMap::with_capacity(6); - /// let mut keys: Vec<Rc<str>> = Vec::with_capacity(6); - /// - /// for (value, key) in ["a", "b", "c", "d", "e", "f"].into_iter().enumerate() { - /// let rc_key: Rc<str> = Rc::from(key); - /// keys.push(rc_key.clone()); - /// map.insert(rc_key.clone(), value); - /// } - /// - /// assert!(keys.iter().all(|key| Rc::strong_count(key) == 2)); - /// - /// // It doesn't matter that we kind of use a vector with the same keys, - /// // because all keys will be newly created from the references - /// reclaim_memory(&mut map, &keys); - /// - /// assert!(keys.iter().all(|key| Rc::strong_count(key) == 1)); - /// - /// fn reclaim_memory(map: &mut HashMap<Rc<str>, usize>, keys: &[Rc<str>]) { - /// for key in keys { - /// if let EntryRef::Occupied(entry) = map.entry_ref(key.as_ref()) { - /// // Replaces the entry's key with our version of it in `keys`. - /// entry.replace_key(); - /// } - /// } - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_key(self) -> K - where - K: From<&'b Q>, - { - let entry = unsafe { self.elem.as_mut() }; - mem::replace(&mut entry.0, self.key.unwrap().into_owned()) - } - - /// Provides shared access to the key and owned access to the value of - /// the entry and allows to replace or remove it based on the - /// value of the returned option. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::EntryRef; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// map.insert("poneyland".to_string(), 42); - /// - /// let entry = match map.entry_ref("poneyland") { - /// EntryRef::Occupied(e) => { - /// e.replace_entry_with(|k, v| { - /// assert_eq!(k, "poneyland"); - /// assert_eq!(v, 42); - /// Some(v + 1) - /// }) - /// } - /// EntryRef::Vacant(_) => panic!(), - /// }; - /// - /// match entry { - /// EntryRef::Occupied(e) => { - /// assert_eq!(e.key(), "poneyland"); - /// assert_eq!(e.get(), &43); - /// } - /// EntryRef::Vacant(_) => panic!(), - /// } - /// - /// assert_eq!(map["poneyland"], 43); - /// - /// let entry = match map.entry_ref("poneyland") { - /// EntryRef::Occupied(e) => e.replace_entry_with(|_k, _v| None), - /// EntryRef::Vacant(_) => panic!(), - /// }; - /// - /// match entry { - /// EntryRef::Vacant(e) => { - /// assert_eq!(e.key(), "poneyland"); - /// } - /// EntryRef::Occupied(_) => panic!(), - /// } - /// - /// assert!(!map.contains_key("poneyland")); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_entry_with<F>(self, f: F) -> EntryRef<'a, 'b, K, Q, V, S, A> - where - F: FnOnce(&Q, V) -> Option<V>, - K: Borrow<Q>, - { - unsafe { - let mut spare_key = None; - - self.table - .table - .replace_bucket_with(self.elem.clone(), |(key, value)| { - if let Some(new_value) = f(key.borrow(), value) { - Some((key, new_value)) - } else { - spare_key = Some(KeyOrRef::Owned(key)); - None - } - }); - - if let Some(key) = spare_key { - EntryRef::Vacant(VacantEntryRef { - hash: self.hash, - key, - table: self.table, - }) - } else { - EntryRef::Occupied(self) - } - } - } -} - -impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator + Clone> VacantEntryRef<'a, 'b, K, Q, V, S, A> { - /// Gets a reference to the key that would be used when inserting a value - /// through the `VacantEntryRef`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// let key: &str = "poneyland"; - /// assert_eq!(map.entry_ref(key).key(), "poneyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &Q - where - K: Borrow<Q>, - { - self.key.as_ref() - } - - /// Take ownership of the key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{EntryRef, HashMap}; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// let key: &str = "poneyland"; - /// - /// match map.entry_ref(key) { - /// EntryRef::Occupied(_) => panic!(), - /// EntryRef::Vacant(v) => assert_eq!(v.into_key(), "poneyland".to_owned()), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_key(self) -> K - where - K: From<&'b Q>, - { - self.key.into_owned() - } - - /// Sets the value of the entry with the VacantEntryRef's key, - /// and returns a mutable reference to it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::EntryRef; - /// - /// let mut map: HashMap<String, u32> = HashMap::new(); - /// let key: &str = "poneyland"; - /// - /// if let EntryRef::Vacant(o) = map.entry_ref(key) { - /// o.insert(37); - /// } - /// assert_eq!(map["poneyland"], 37); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, value: V) -> &'a mut V - where - K: Hash + From<&'b Q>, - S: BuildHasher, - { - let table = &mut self.table.table; - let entry = table.insert_entry( - self.hash, - (self.key.into_owned(), value), - make_hasher::<_, V, S>(&self.table.hash_builder), - ); - &mut entry.1 - } - - #[cfg_attr(feature = "inline-more", inline)] - fn insert_entry(self, value: V) -> OccupiedEntryRef<'a, 'b, K, Q, V, S, A> - where - K: Hash + From<&'b Q>, - S: BuildHasher, - { - let elem = self.table.table.insert( - self.hash, - (self.key.into_owned(), value), - make_hasher::<_, V, S>(&self.table.hash_builder), - ); - OccupiedEntryRef { - hash: self.hash, - key: None, - elem, - table: self.table, - } - } -} - -impl<K, V, S, A> FromIterator<(K, V)> for HashMap<K, V, S, A> -where - K: Eq + Hash, - S: BuildHasher + Default, - A: Default + Allocator + Clone, -{ - #[cfg_attr(feature = "inline-more", inline)] - fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self { - let iter = iter.into_iter(); - let mut map = - Self::with_capacity_and_hasher_in(iter.size_hint().0, S::default(), A::default()); - iter.for_each(|(k, v)| { - map.insert(k, v); - }); - map - } -} - -/// Inserts all new key-values from the iterator and replaces values with existing -/// keys with new values returned from the iterator. -impl<K, V, S, A> Extend<(K, V)> for HashMap<K, V, S, A> -where - K: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - /// Inserts all new key-values from the iterator to existing `HashMap<K, V, S, A>`. - /// Replace values with existing keys with new values returned from the iterator. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, 100); - /// - /// let some_iter = [(1, 1), (2, 2)].into_iter(); - /// map.extend(some_iter); - /// // Replace values with existing keys with new values returned from the iterator. - /// // So that the map.get(&1) doesn't return Some(&100). - /// assert_eq!(map.get(&1), Some(&1)); - /// - /// let some_vec: Vec<_> = vec![(3, 3), (4, 4)]; - /// map.extend(some_vec); - /// - /// let some_arr = [(5, 5), (6, 6)]; - /// map.extend(some_arr); - /// let old_map_len = map.len(); - /// - /// // You can also extend from another HashMap - /// let mut new_map = HashMap::new(); - /// new_map.extend(map); - /// assert_eq!(new_map.len(), old_map_len); - /// - /// let mut vec: Vec<_> = new_map.into_iter().collect(); - /// // The `IntoIter` iterator produces items in arbitrary order, so the - /// // items must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) { - // Keys may be already present or show multiple times in the iterator. - // Reserve the entire hint lower bound if the map is empty. - // Otherwise reserve half the hint (rounded up), so the map - // will only resize twice in the worst case. - let iter = iter.into_iter(); - let reserve = if self.is_empty() { - iter.size_hint().0 - } else { - (iter.size_hint().0 + 1) / 2 - }; - self.reserve(reserve); - iter.for_each(move |(k, v)| { - self.insert(k, v); - }); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_one(&mut self, (k, v): (K, V)) { - self.insert(k, v); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_reserve(&mut self, additional: usize) { - // Keys may be already present or show multiple times in the iterator. - // Reserve the entire hint lower bound if the map is empty. - // Otherwise reserve half the hint (rounded up), so the map - // will only resize twice in the worst case. - let reserve = if self.is_empty() { - additional - } else { - (additional + 1) / 2 - }; - self.reserve(reserve); - } -} - -/// Inserts all new key-values from the iterator and replaces values with existing -/// keys with new values returned from the iterator. -impl<'a, K, V, S, A> Extend<(&'a K, &'a V)> for HashMap<K, V, S, A> -where - K: Eq + Hash + Copy, - V: Copy, - S: BuildHasher, - A: Allocator + Clone, -{ - /// Inserts all new key-values from the iterator to existing `HashMap<K, V, S, A>`. - /// Replace values with existing keys with new values returned from the iterator. - /// The keys and values must implement [`Copy`] trait. - /// - /// [`Copy`]: https://doc.rust-lang.org/core/marker/trait.Copy.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, 100); - /// - /// let arr = [(1, 1), (2, 2)]; - /// let some_iter = arr.iter().map(|(k, v)| (k, v)); - /// map.extend(some_iter); - /// // Replace values with existing keys with new values returned from the iterator. - /// // So that the map.get(&1) doesn't return Some(&100). - /// assert_eq!(map.get(&1), Some(&1)); - /// - /// let some_vec: Vec<_> = vec![(3, 3), (4, 4)]; - /// map.extend(some_vec.iter().map(|(k, v)| (k, v))); - /// - /// let some_arr = [(5, 5), (6, 6)]; - /// map.extend(some_arr.iter().map(|(k, v)| (k, v))); - /// - /// // You can also extend from another HashMap - /// let mut new_map = HashMap::new(); - /// new_map.extend(&map); - /// assert_eq!(new_map, map); - /// - /// let mut vec: Vec<_> = new_map.into_iter().collect(); - /// // The `IntoIter` iterator produces items in arbitrary order, so the - /// // items must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) { - self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_one(&mut self, (k, v): (&'a K, &'a V)) { - self.insert(*k, *v); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_reserve(&mut self, additional: usize) { - Extend::<(K, V)>::extend_reserve(self, additional); - } -} - -/// Inserts all new key-values from the iterator and replaces values with existing -/// keys with new values returned from the iterator. -impl<'a, K, V, S, A> Extend<&'a (K, V)> for HashMap<K, V, S, A> -where - K: Eq + Hash + Copy, - V: Copy, - S: BuildHasher, - A: Allocator + Clone, -{ - /// Inserts all new key-values from the iterator to existing `HashMap<K, V, S, A>`. - /// Replace values with existing keys with new values returned from the iterator. - /// The keys and values must implement [`Copy`] trait. - /// - /// [`Copy`]: https://doc.rust-lang.org/core/marker/trait.Copy.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, 100); - /// - /// let arr = [(1, 1), (2, 2)]; - /// let some_iter = arr.iter(); - /// map.extend(some_iter); - /// // Replace values with existing keys with new values returned from the iterator. - /// // So that the map.get(&1) doesn't return Some(&100). - /// assert_eq!(map.get(&1), Some(&1)); - /// - /// let some_vec: Vec<_> = vec![(3, 3), (4, 4)]; - /// map.extend(&some_vec); - /// - /// let some_arr = [(5, 5), (6, 6)]; - /// map.extend(&some_arr); - /// - /// let mut vec: Vec<_> = map.into_iter().collect(); - /// // The `IntoIter` iterator produces items in arbitrary order, so the - /// // items must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn extend<T: IntoIterator<Item = &'a (K, V)>>(&mut self, iter: T) { - self.extend(iter.into_iter().map(|&(key, value)| (key, value))); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_one(&mut self, &(k, v): &'a (K, V)) { - self.insert(k, v); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_reserve(&mut self, additional: usize) { - Extend::<(K, V)>::extend_reserve(self, additional); - } -} - -#[allow(dead_code)] -fn assert_covariance() { - fn map_key<'new>(v: HashMap<&'static str, u8>) -> HashMap<&'new str, u8> { - v - } - fn map_val<'new>(v: HashMap<u8, &'static str>) -> HashMap<u8, &'new str> { - v - } - fn iter_key<'a, 'new>(v: Iter<'a, &'static str, u8>) -> Iter<'a, &'new str, u8> { - v - } - fn iter_val<'a, 'new>(v: Iter<'a, u8, &'static str>) -> Iter<'a, u8, &'new str> { - v - } - fn into_iter_key<'new, A: Allocator + Clone>( - v: IntoIter<&'static str, u8, A>, - ) -> IntoIter<&'new str, u8, A> { - v - } - fn into_iter_val<'new, A: Allocator + Clone>( - v: IntoIter<u8, &'static str, A>, - ) -> IntoIter<u8, &'new str, A> { - v - } - fn keys_key<'a, 'new>(v: Keys<'a, &'static str, u8>) -> Keys<'a, &'new str, u8> { - v - } - fn keys_val<'a, 'new>(v: Keys<'a, u8, &'static str>) -> Keys<'a, u8, &'new str> { - v - } - fn values_key<'a, 'new>(v: Values<'a, &'static str, u8>) -> Values<'a, &'new str, u8> { - v - } - fn values_val<'a, 'new>(v: Values<'a, u8, &'static str>) -> Values<'a, u8, &'new str> { - v - } - fn drain<'new>( - d: Drain<'static, &'static str, &'static str>, - ) -> Drain<'new, &'new str, &'new str> { - d - } -} - -#[cfg(test)] -mod test_map { - use super::DefaultHashBuilder; - use super::Entry::{Occupied, Vacant}; - use super::EntryRef; - use super::{HashMap, RawEntryMut}; - use rand::{rngs::SmallRng, Rng, SeedableRng}; - use std::borrow::ToOwned; - use std::cell::RefCell; - use std::usize; - use std::vec::Vec; - - #[test] - fn test_zero_capacities() { - type HM = HashMap<i32, i32>; - - let m = HM::new(); - assert_eq!(m.capacity(), 0); - - let m = HM::default(); - assert_eq!(m.capacity(), 0); - - let m = HM::with_hasher(DefaultHashBuilder::default()); - assert_eq!(m.capacity(), 0); - - let m = HM::with_capacity(0); - assert_eq!(m.capacity(), 0); - - let m = HM::with_capacity_and_hasher(0, DefaultHashBuilder::default()); - assert_eq!(m.capacity(), 0); - - let mut m = HM::new(); - m.insert(1, 1); - m.insert(2, 2); - m.remove(&1); - m.remove(&2); - m.shrink_to_fit(); - assert_eq!(m.capacity(), 0); - - let mut m = HM::new(); - m.reserve(0); - assert_eq!(m.capacity(), 0); - } - - #[test] - fn test_create_capacity_zero() { - let mut m = HashMap::with_capacity(0); - - assert!(m.insert(1, 1).is_none()); - - assert!(m.contains_key(&1)); - assert!(!m.contains_key(&0)); - } - - #[test] - fn test_insert() { - let mut m = HashMap::new(); - assert_eq!(m.len(), 0); - assert!(m.insert(1, 2).is_none()); - assert_eq!(m.len(), 1); - assert!(m.insert(2, 4).is_none()); - assert_eq!(m.len(), 2); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&2).unwrap(), 4); - } - - #[test] - fn test_clone() { - let mut m = HashMap::new(); - assert_eq!(m.len(), 0); - assert!(m.insert(1, 2).is_none()); - assert_eq!(m.len(), 1); - assert!(m.insert(2, 4).is_none()); - assert_eq!(m.len(), 2); - #[allow(clippy::redundant_clone)] - let m2 = m.clone(); - assert_eq!(*m2.get(&1).unwrap(), 2); - assert_eq!(*m2.get(&2).unwrap(), 4); - assert_eq!(m2.len(), 2); - } - - #[test] - fn test_clone_from() { - let mut m = HashMap::new(); - let mut m2 = HashMap::new(); - assert_eq!(m.len(), 0); - assert!(m.insert(1, 2).is_none()); - assert_eq!(m.len(), 1); - assert!(m.insert(2, 4).is_none()); - assert_eq!(m.len(), 2); - m2.clone_from(&m); - assert_eq!(*m2.get(&1).unwrap(), 2); - assert_eq!(*m2.get(&2).unwrap(), 4); - assert_eq!(m2.len(), 2); - } - - thread_local! { static DROP_VECTOR: RefCell<Vec<i32>> = RefCell::new(Vec::new()) } - - #[derive(Hash, PartialEq, Eq)] - struct Droppable { - k: usize, - } - - impl Droppable { - fn new(k: usize) -> Droppable { - DROP_VECTOR.with(|slot| { - slot.borrow_mut()[k] += 1; - }); - - Droppable { k } - } - } - - impl Drop for Droppable { - fn drop(&mut self) { - DROP_VECTOR.with(|slot| { - slot.borrow_mut()[self.k] -= 1; - }); - } - } - - impl Clone for Droppable { - fn clone(&self) -> Self { - Droppable::new(self.k) - } - } - - #[test] - fn test_drops() { - DROP_VECTOR.with(|slot| { - *slot.borrow_mut() = vec![0; 200]; - }); - - { - let mut m = HashMap::new(); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - - for i in 0..100 { - let d1 = Droppable::new(i); - let d2 = Droppable::new(i + 100); - m.insert(d1, d2); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - for i in 0..50 { - let k = Droppable::new(i); - let v = m.remove(&k); - - assert!(v.is_some()); - - DROP_VECTOR.with(|v| { - assert_eq!(v.borrow()[i], 1); - assert_eq!(v.borrow()[i + 100], 1); - }); - } - - DROP_VECTOR.with(|v| { - for i in 0..50 { - assert_eq!(v.borrow()[i], 0); - assert_eq!(v.borrow()[i + 100], 0); - } - - for i in 50..100 { - assert_eq!(v.borrow()[i], 1); - assert_eq!(v.borrow()[i + 100], 1); - } - }); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - } - - #[test] - fn test_into_iter_drops() { - DROP_VECTOR.with(|v| { - *v.borrow_mut() = vec![0; 200]; - }); - - let hm = { - let mut hm = HashMap::new(); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - - for i in 0..100 { - let d1 = Droppable::new(i); - let d2 = Droppable::new(i + 100); - hm.insert(d1, d2); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - hm - }; - - // By the way, ensure that cloning doesn't screw up the dropping. - drop(hm.clone()); - - { - let mut half = hm.into_iter().take(50); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - #[allow(clippy::let_underscore_drop)] // kind-of a false positive - for _ in half.by_ref() {} - - DROP_VECTOR.with(|v| { - let nk = (0..100).filter(|&i| v.borrow()[i] == 1).count(); - - let nv = (0..100).filter(|&i| v.borrow()[i + 100] == 1).count(); - - assert_eq!(nk, 50); - assert_eq!(nv, 50); - }); - }; - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - } - - #[test] - fn test_empty_remove() { - let mut m: HashMap<i32, bool> = HashMap::new(); - assert_eq!(m.remove(&0), None); - } - - #[test] - fn test_empty_entry() { - let mut m: HashMap<i32, bool> = HashMap::new(); - match m.entry(0) { - Occupied(_) => panic!(), - Vacant(_) => {} - } - assert!(*m.entry(0).or_insert(true)); - assert_eq!(m.len(), 1); - } - - #[test] - fn test_empty_entry_ref() { - let mut m: HashMap<std::string::String, bool> = HashMap::new(); - match m.entry_ref("poneyland") { - EntryRef::Occupied(_) => panic!(), - EntryRef::Vacant(_) => {} - } - assert!(*m.entry_ref("poneyland").or_insert(true)); - assert_eq!(m.len(), 1); - } - - #[test] - fn test_empty_iter() { - let mut m: HashMap<i32, bool> = HashMap::new(); - assert_eq!(m.drain().next(), None); - assert_eq!(m.keys().next(), None); - assert_eq!(m.values().next(), None); - assert_eq!(m.values_mut().next(), None); - assert_eq!(m.iter().next(), None); - assert_eq!(m.iter_mut().next(), None); - assert_eq!(m.len(), 0); - assert!(m.is_empty()); - assert_eq!(m.into_iter().next(), None); - } - - #[test] - #[cfg_attr(miri, ignore)] // FIXME: takes too long - fn test_lots_of_insertions() { - let mut m = HashMap::new(); - - // Try this a few times to make sure we never screw up the hashmap's - // internal state. - for _ in 0..10 { - assert!(m.is_empty()); - - for i in 1..1001 { - assert!(m.insert(i, i).is_none()); - - for j in 1..=i { - let r = m.get(&j); - assert_eq!(r, Some(&j)); - } - - for j in i + 1..1001 { - let r = m.get(&j); - assert_eq!(r, None); - } - } - - for i in 1001..2001 { - assert!(!m.contains_key(&i)); - } - - // remove forwards - for i in 1..1001 { - assert!(m.remove(&i).is_some()); - - for j in 1..=i { - assert!(!m.contains_key(&j)); - } - - for j in i + 1..1001 { - assert!(m.contains_key(&j)); - } - } - - for i in 1..1001 { - assert!(!m.contains_key(&i)); - } - - for i in 1..1001 { - assert!(m.insert(i, i).is_none()); - } - - // remove backwards - for i in (1..1001).rev() { - assert!(m.remove(&i).is_some()); - - for j in i..1001 { - assert!(!m.contains_key(&j)); - } - - for j in 1..i { - assert!(m.contains_key(&j)); - } - } - } - } - - #[test] - fn test_find_mut() { - let mut m = HashMap::new(); - assert!(m.insert(1, 12).is_none()); - assert!(m.insert(2, 8).is_none()); - assert!(m.insert(5, 14).is_none()); - let new = 100; - match m.get_mut(&5) { - None => panic!(), - Some(x) => *x = new, - } - assert_eq!(m.get(&5), Some(&new)); - } - - #[test] - fn test_insert_overwrite() { - let mut m = HashMap::new(); - assert!(m.insert(1, 2).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert!(m.insert(1, 3).is_some()); - assert_eq!(*m.get(&1).unwrap(), 3); - } - - #[test] - fn test_insert_conflicts() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(5, 3).is_none()); - assert!(m.insert(9, 4).is_none()); - assert_eq!(*m.get(&9).unwrap(), 4); - assert_eq!(*m.get(&5).unwrap(), 3); - assert_eq!(*m.get(&1).unwrap(), 2); - } - - #[test] - fn test_conflict_remove() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert!(m.insert(5, 3).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&5).unwrap(), 3); - assert!(m.insert(9, 4).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&5).unwrap(), 3); - assert_eq!(*m.get(&9).unwrap(), 4); - assert!(m.remove(&1).is_some()); - assert_eq!(*m.get(&9).unwrap(), 4); - assert_eq!(*m.get(&5).unwrap(), 3); - } - - #[test] - fn test_insert_unique_unchecked() { - let mut map = HashMap::new(); - let (k1, v1) = map.insert_unique_unchecked(10, 11); - assert_eq!((&10, &mut 11), (k1, v1)); - let (k2, v2) = map.insert_unique_unchecked(20, 21); - assert_eq!((&20, &mut 21), (k2, v2)); - assert_eq!(Some(&11), map.get(&10)); - assert_eq!(Some(&21), map.get(&20)); - assert_eq!(None, map.get(&30)); - } - - #[test] - fn test_is_empty() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert!(!m.is_empty()); - assert!(m.remove(&1).is_some()); - assert!(m.is_empty()); - } - - #[test] - fn test_remove() { - let mut m = HashMap::new(); - m.insert(1, 2); - assert_eq!(m.remove(&1), Some(2)); - assert_eq!(m.remove(&1), None); - } - - #[test] - fn test_remove_entry() { - let mut m = HashMap::new(); - m.insert(1, 2); - assert_eq!(m.remove_entry(&1), Some((1, 2))); - assert_eq!(m.remove(&1), None); - } - - #[test] - fn test_iterate() { - let mut m = HashMap::with_capacity(4); - for i in 0..32 { - assert!(m.insert(i, i * 2).is_none()); - } - assert_eq!(m.len(), 32); - - let mut observed: u32 = 0; - - for (k, v) in &m { - assert_eq!(*v, *k * 2); - observed |= 1 << *k; - } - assert_eq!(observed, 0xFFFF_FFFF); - } - - #[test] - fn test_keys() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_iter().collect(); - let keys: Vec<_> = map.keys().copied().collect(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_iter().collect(); - let values: Vec<_> = map.values().copied().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_values_mut() { - let vec = vec![(1, 1), (2, 2), (3, 3)]; - let mut map: HashMap<_, _> = vec.into_iter().collect(); - for value in map.values_mut() { - *value *= 2; - } - let values: Vec<_> = map.values().copied().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&2)); - assert!(values.contains(&4)); - assert!(values.contains(&6)); - } - - #[test] - fn test_into_keys() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_iter().collect(); - let keys: Vec<_> = map.into_keys().collect(); - - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_into_values() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_iter().collect(); - let values: Vec<_> = map.into_values().collect(); - - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_find() { - let mut m = HashMap::new(); - assert!(m.get(&1).is_none()); - m.insert(1, 2); - match m.get(&1) { - None => panic!(), - Some(v) => assert_eq!(*v, 2), - } - } - - #[test] - fn test_eq() { - let mut m1 = HashMap::new(); - m1.insert(1, 2); - m1.insert(2, 3); - m1.insert(3, 4); - - let mut m2 = HashMap::new(); - m2.insert(1, 2); - m2.insert(2, 3); - - assert!(m1 != m2); - - m2.insert(3, 4); - - assert_eq!(m1, m2); - } - - #[test] - fn test_show() { - let mut map = HashMap::new(); - let empty: HashMap<i32, i32> = HashMap::new(); - - map.insert(1, 2); - map.insert(3, 4); - - let map_str = format!("{:?}", map); - - assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); - assert_eq!(format!("{:?}", empty), "{}"); - } - - #[test] - fn test_expand() { - let mut m = HashMap::new(); - - assert_eq!(m.len(), 0); - assert!(m.is_empty()); - - let mut i = 0; - let old_raw_cap = m.raw_capacity(); - while old_raw_cap == m.raw_capacity() { - m.insert(i, i); - i += 1; - } - - assert_eq!(m.len(), i); - assert!(!m.is_empty()); - } - - #[test] - fn test_behavior_resize_policy() { - let mut m = HashMap::new(); - - assert_eq!(m.len(), 0); - assert_eq!(m.raw_capacity(), 1); - assert!(m.is_empty()); - - m.insert(0, 0); - m.remove(&0); - assert!(m.is_empty()); - let initial_raw_cap = m.raw_capacity(); - m.reserve(initial_raw_cap); - let raw_cap = m.raw_capacity(); - - assert_eq!(raw_cap, initial_raw_cap * 2); - - let mut i = 0; - for _ in 0..raw_cap * 3 / 4 { - m.insert(i, i); - i += 1; - } - // three quarters full - - assert_eq!(m.len(), i); - assert_eq!(m.raw_capacity(), raw_cap); - - for _ in 0..raw_cap / 4 { - m.insert(i, i); - i += 1; - } - // half full - - let new_raw_cap = m.raw_capacity(); - assert_eq!(new_raw_cap, raw_cap * 2); - - for _ in 0..raw_cap / 2 - 1 { - i -= 1; - m.remove(&i); - assert_eq!(m.raw_capacity(), new_raw_cap); - } - // A little more than one quarter full. - m.shrink_to_fit(); - assert_eq!(m.raw_capacity(), raw_cap); - // again, a little more than half full - for _ in 0..raw_cap / 2 { - i -= 1; - m.remove(&i); - } - m.shrink_to_fit(); - - assert_eq!(m.len(), i); - assert!(!m.is_empty()); - assert_eq!(m.raw_capacity(), initial_raw_cap); - } - - #[test] - fn test_reserve_shrink_to_fit() { - let mut m = HashMap::new(); - m.insert(0, 0); - m.remove(&0); - assert!(m.capacity() >= m.len()); - for i in 0..128 { - m.insert(i, i); - } - m.reserve(256); - - let usable_cap = m.capacity(); - for i in 128..(128 + 256) { - m.insert(i, i); - assert_eq!(m.capacity(), usable_cap); - } - - for i in 100..(128 + 256) { - assert_eq!(m.remove(&i), Some(i)); - } - m.shrink_to_fit(); - - assert_eq!(m.len(), 100); - assert!(!m.is_empty()); - assert!(m.capacity() >= m.len()); - - for i in 0..100 { - assert_eq!(m.remove(&i), Some(i)); - } - m.shrink_to_fit(); - m.insert(0, 0); - - assert_eq!(m.len(), 1); - assert!(m.capacity() >= m.len()); - assert_eq!(m.remove(&0), Some(0)); - } - - #[test] - fn test_from_iter() { - let xs = [(1, 1), (2, 2), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().copied().collect(); - - for &(k, v) in &xs { - assert_eq!(map.get(&k), Some(&v)); - } - - assert_eq!(map.iter().len(), xs.len() - 1); - } - - #[test] - fn test_size_hint() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().copied().collect(); - - let mut iter = map.iter(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.size_hint(), (3, Some(3))); - } - - #[test] - fn test_iter_len() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().copied().collect(); - - let mut iter = map.iter(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.len(), 3); - } - - #[test] - fn test_mut_size_hint() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let mut map: HashMap<_, _> = xs.iter().copied().collect(); - - let mut iter = map.iter_mut(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.size_hint(), (3, Some(3))); - } - - #[test] - fn test_iter_mut_len() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let mut map: HashMap<_, _> = xs.iter().copied().collect(); - - let mut iter = map.iter_mut(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.len(), 3); - } - - #[test] - fn test_index() { - let mut map = HashMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[&2], 1); - } - - #[test] - #[should_panic] - fn test_index_nonexistent() { - let mut map = HashMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - #[allow(clippy::no_effect)] // false positive lint - map[&4]; - } - - #[test] - fn test_entry() { - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: HashMap<_, _> = xs.iter().copied().collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - let new_v = (*v) * 10; - *v = new_v; - } - } - assert_eq!(map.get(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get(&3), None); - assert_eq!(map.len(), 5); - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); - } - - #[test] - fn test_entry_ref() { - let xs = [ - ("One".to_owned(), 10), - ("Two".to_owned(), 20), - ("Three".to_owned(), 30), - ("Four".to_owned(), 40), - ("Five".to_owned(), 50), - ("Six".to_owned(), 60), - ]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - // Existing key (insert) - match map.entry_ref("One") { - EntryRef::Vacant(_) => unreachable!(), - EntryRef::Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get("One").unwrap(), &100); - assert_eq!(map.len(), 6); - - // Existing key (update) - match map.entry_ref("Two") { - EntryRef::Vacant(_) => unreachable!(), - EntryRef::Occupied(mut view) => { - let v = view.get_mut(); - let new_v = (*v) * 10; - *v = new_v; - } - } - assert_eq!(map.get("Two").unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry_ref("Three") { - EntryRef::Vacant(_) => unreachable!(), - EntryRef::Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get("Three"), None); - assert_eq!(map.len(), 5); - - // Inexistent key (insert) - match map.entry_ref("Ten") { - EntryRef::Occupied(_) => unreachable!(), - EntryRef::Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get("Ten").unwrap(), &1000); - assert_eq!(map.len(), 6); - } - - #[test] - fn test_entry_take_doesnt_corrupt() { - #![allow(deprecated)] //rand - // Test for #19292 - fn check(m: &HashMap<i32, ()>) { - for k in m.keys() { - assert!(m.contains_key(k), "{} is in keys() but not in the map?", k); - } - } - - let mut m = HashMap::new(); - - let mut rng = { - let seed = u64::from_le_bytes(*b"testseed"); - SmallRng::seed_from_u64(seed) - }; - - // Populate the map with some items. - for _ in 0..50 { - let x = rng.gen_range(-10..10); - m.insert(x, ()); - } - - for _ in 0..1000 { - let x = rng.gen_range(-10..10); - match m.entry(x) { - Vacant(_) => {} - Occupied(e) => { - e.remove(); - } - } - - check(&m); - } - } - - #[test] - fn test_entry_ref_take_doesnt_corrupt() { - #![allow(deprecated)] //rand - // Test for #19292 - fn check(m: &HashMap<std::string::String, ()>) { - for k in m.keys() { - assert!(m.contains_key(k), "{} is in keys() but not in the map?", k); - } - } - - let mut m = HashMap::new(); - - let mut rng = { - let seed = u64::from_le_bytes(*b"testseed"); - SmallRng::seed_from_u64(seed) - }; - - // Populate the map with some items. - for _ in 0..50 { - let mut x = std::string::String::with_capacity(1); - x.push(rng.gen_range('a'..='z')); - m.insert(x, ()); - } - - for _ in 0..1000 { - let mut x = std::string::String::with_capacity(1); - x.push(rng.gen_range('a'..='z')); - match m.entry_ref(x.as_str()) { - EntryRef::Vacant(_) => {} - EntryRef::Occupied(e) => { - e.remove(); - } - } - - check(&m); - } - } - - #[test] - fn test_extend_ref_k_ref_v() { - let mut a = HashMap::new(); - a.insert(1, "one"); - let mut b = HashMap::new(); - b.insert(2, "two"); - b.insert(3, "three"); - - a.extend(&b); - - assert_eq!(a.len(), 3); - assert_eq!(a[&1], "one"); - assert_eq!(a[&2], "two"); - assert_eq!(a[&3], "three"); - } - - #[test] - fn test_extend_ref_kv_tuple() { - use std::ops::AddAssign; - let mut a = HashMap::new(); - a.insert(0, 0); - - fn create_arr<T: AddAssign<T> + Copy, const N: usize>(start: T, step: T) -> [(T, T); N] { - let mut outs: [(T, T); N] = [(start, start); N]; - let mut element = step; - outs.iter_mut().skip(1).for_each(|(k, v)| { - *k += element; - *v += element; - element += step; - }); - outs - } - - let for_iter: Vec<_> = (0..100).map(|i| (i, i)).collect(); - let iter = for_iter.iter(); - let vec: Vec<_> = (100..200).map(|i| (i, i)).collect(); - a.extend(iter); - a.extend(&vec); - a.extend(create_arr::<i32, 100>(200, 1)); - - assert_eq!(a.len(), 300); - - for item in 0..300 { - assert_eq!(a[&item], item); - } - } - - #[test] - fn test_capacity_not_less_than_len() { - let mut a = HashMap::new(); - let mut item = 0; - - for _ in 0..116 { - a.insert(item, 0); - item += 1; - } - - assert!(a.capacity() > a.len()); - - let free = a.capacity() - a.len(); - for _ in 0..free { - a.insert(item, 0); - item += 1; - } - - assert_eq!(a.len(), a.capacity()); - - // Insert at capacity should cause allocation. - a.insert(item, 0); - assert!(a.capacity() > a.len()); - } - - #[test] - fn test_occupied_entry_key() { - let mut a = HashMap::new(); - let key = "hello there"; - let value = "value goes here"; - assert!(a.is_empty()); - a.insert(key, value); - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - - match a.entry(key) { - Vacant(_) => panic!(), - Occupied(e) => assert_eq!(key, *e.key()), - } - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - } - - #[test] - fn test_occupied_entry_ref_key() { - let mut a = HashMap::new(); - let key = "hello there"; - let value = "value goes here"; - assert!(a.is_empty()); - a.insert(key.to_owned(), value); - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - - match a.entry_ref(key) { - EntryRef::Vacant(_) => panic!(), - EntryRef::Occupied(e) => assert_eq!(key, e.key()), - } - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - } - - #[test] - fn test_vacant_entry_key() { - let mut a = HashMap::new(); - let key = "hello there"; - let value = "value goes here"; - - assert!(a.is_empty()); - match a.entry(key) { - Occupied(_) => panic!(), - Vacant(e) => { - assert_eq!(key, *e.key()); - e.insert(value); - } - } - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - } - - #[test] - fn test_vacant_entry_ref_key() { - let mut a: HashMap<std::string::String, &str> = HashMap::new(); - let key = "hello there"; - let value = "value goes here"; - - assert!(a.is_empty()); - match a.entry_ref(key) { - EntryRef::Occupied(_) => panic!(), - EntryRef::Vacant(e) => { - assert_eq!(key, e.key()); - e.insert(value); - } - } - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - } - - #[test] - fn test_occupied_entry_replace_entry_with() { - let mut a = HashMap::new(); - - let key = "a key"; - let value = "an initial value"; - let new_value = "a new value"; - - let entry = a.entry(key).insert(value).replace_entry_with(|k, v| { - assert_eq!(k, &key); - assert_eq!(v, value); - Some(new_value) - }); - - match entry { - Occupied(e) => { - assert_eq!(e.key(), &key); - assert_eq!(e.get(), &new_value); - } - Vacant(_) => panic!(), - } - - assert_eq!(a[key], new_value); - assert_eq!(a.len(), 1); - - let entry = match a.entry(key) { - Occupied(e) => e.replace_entry_with(|k, v| { - assert_eq!(k, &key); - assert_eq!(v, new_value); - None - }), - Vacant(_) => panic!(), - }; - - match entry { - Vacant(e) => assert_eq!(e.key(), &key), - Occupied(_) => panic!(), - } - - assert!(!a.contains_key(key)); - assert_eq!(a.len(), 0); - } - - #[test] - fn test_occupied_entry_ref_replace_entry_with() { - let mut a: HashMap<std::string::String, &str> = HashMap::new(); - - let key = "a key"; - let value = "an initial value"; - let new_value = "a new value"; - - let entry = a.entry_ref(key).insert(value).replace_entry_with(|k, v| { - assert_eq!(k, key); - assert_eq!(v, value); - Some(new_value) - }); - - match entry { - EntryRef::Occupied(e) => { - assert_eq!(e.key(), key); - assert_eq!(e.get(), &new_value); - } - EntryRef::Vacant(_) => panic!(), - } - - assert_eq!(a[key], new_value); - assert_eq!(a.len(), 1); - - let entry = match a.entry_ref(key) { - EntryRef::Occupied(e) => e.replace_entry_with(|k, v| { - assert_eq!(k, key); - assert_eq!(v, new_value); - None - }), - EntryRef::Vacant(_) => panic!(), - }; - - match entry { - EntryRef::Vacant(e) => assert_eq!(e.key(), key), - EntryRef::Occupied(_) => panic!(), - } - - assert!(!a.contains_key(key)); - assert_eq!(a.len(), 0); - } - - #[test] - fn test_entry_and_replace_entry_with() { - let mut a = HashMap::new(); - - let key = "a key"; - let value = "an initial value"; - let new_value = "a new value"; - - let entry = a.entry(key).and_replace_entry_with(|_, _| panic!()); - - match entry { - Vacant(e) => assert_eq!(e.key(), &key), - Occupied(_) => panic!(), - } - - a.insert(key, value); - - let entry = a.entry(key).and_replace_entry_with(|k, v| { - assert_eq!(k, &key); - assert_eq!(v, value); - Some(new_value) - }); - - match entry { - Occupied(e) => { - assert_eq!(e.key(), &key); - assert_eq!(e.get(), &new_value); - } - Vacant(_) => panic!(), - } - - assert_eq!(a[key], new_value); - assert_eq!(a.len(), 1); - - let entry = a.entry(key).and_replace_entry_with(|k, v| { - assert_eq!(k, &key); - assert_eq!(v, new_value); - None - }); - - match entry { - Vacant(e) => assert_eq!(e.key(), &key), - Occupied(_) => panic!(), - } - - assert!(!a.contains_key(key)); - assert_eq!(a.len(), 0); - } - - #[test] - fn test_entry_ref_and_replace_entry_with() { - let mut a = HashMap::new(); - - let key = "a key"; - let value = "an initial value"; - let new_value = "a new value"; - - let entry = a.entry_ref(key).and_replace_entry_with(|_, _| panic!()); - - match entry { - EntryRef::Vacant(e) => assert_eq!(e.key(), key), - EntryRef::Occupied(_) => panic!(), - } - - a.insert(key.to_owned(), value); - - let entry = a.entry_ref(key).and_replace_entry_with(|k, v| { - assert_eq!(k, key); - assert_eq!(v, value); - Some(new_value) - }); - - match entry { - EntryRef::Occupied(e) => { - assert_eq!(e.key(), key); - assert_eq!(e.get(), &new_value); - } - EntryRef::Vacant(_) => panic!(), - } - - assert_eq!(a[key], new_value); - assert_eq!(a.len(), 1); - - let entry = a.entry_ref(key).and_replace_entry_with(|k, v| { - assert_eq!(k, key); - assert_eq!(v, new_value); - None - }); - - match entry { - EntryRef::Vacant(e) => assert_eq!(e.key(), key), - EntryRef::Occupied(_) => panic!(), - } - - assert!(!a.contains_key(key)); - assert_eq!(a.len(), 0); - } - - #[test] - fn test_raw_occupied_entry_replace_entry_with() { - let mut a = HashMap::new(); - - let key = "a key"; - let value = "an initial value"; - let new_value = "a new value"; - - let entry = a - .raw_entry_mut() - .from_key(&key) - .insert(key, value) - .replace_entry_with(|k, v| { - assert_eq!(k, &key); - assert_eq!(v, value); - Some(new_value) - }); - - match entry { - RawEntryMut::Occupied(e) => { - assert_eq!(e.key(), &key); - assert_eq!(e.get(), &new_value); - } - RawEntryMut::Vacant(_) => panic!(), - } - - assert_eq!(a[key], new_value); - assert_eq!(a.len(), 1); - - let entry = match a.raw_entry_mut().from_key(&key) { - RawEntryMut::Occupied(e) => e.replace_entry_with(|k, v| { - assert_eq!(k, &key); - assert_eq!(v, new_value); - None - }), - RawEntryMut::Vacant(_) => panic!(), - }; - - match entry { - RawEntryMut::Vacant(_) => {} - RawEntryMut::Occupied(_) => panic!(), - } - - assert!(!a.contains_key(key)); - assert_eq!(a.len(), 0); - } - - #[test] - fn test_raw_entry_and_replace_entry_with() { - let mut a = HashMap::new(); - - let key = "a key"; - let value = "an initial value"; - let new_value = "a new value"; - - let entry = a - .raw_entry_mut() - .from_key(&key) - .and_replace_entry_with(|_, _| panic!()); - - match entry { - RawEntryMut::Vacant(_) => {} - RawEntryMut::Occupied(_) => panic!(), - } - - a.insert(key, value); - - let entry = a - .raw_entry_mut() - .from_key(&key) - .and_replace_entry_with(|k, v| { - assert_eq!(k, &key); - assert_eq!(v, value); - Some(new_value) - }); - - match entry { - RawEntryMut::Occupied(e) => { - assert_eq!(e.key(), &key); - assert_eq!(e.get(), &new_value); - } - RawEntryMut::Vacant(_) => panic!(), - } - - assert_eq!(a[key], new_value); - assert_eq!(a.len(), 1); - - let entry = a - .raw_entry_mut() - .from_key(&key) - .and_replace_entry_with(|k, v| { - assert_eq!(k, &key); - assert_eq!(v, new_value); - None - }); - - match entry { - RawEntryMut::Vacant(_) => {} - RawEntryMut::Occupied(_) => panic!(), - } - - assert!(!a.contains_key(key)); - assert_eq!(a.len(), 0); - } - - #[test] - fn test_replace_entry_with_doesnt_corrupt() { - #![allow(deprecated)] //rand - // Test for #19292 - fn check(m: &HashMap<i32, ()>) { - for k in m.keys() { - assert!(m.contains_key(k), "{} is in keys() but not in the map?", k); - } - } - - let mut m = HashMap::new(); - - let mut rng = { - let seed = u64::from_le_bytes(*b"testseed"); - SmallRng::seed_from_u64(seed) - }; - - // Populate the map with some items. - for _ in 0..50 { - let x = rng.gen_range(-10..10); - m.insert(x, ()); - } - - for _ in 0..1000 { - let x = rng.gen_range(-10..10); - m.entry(x).and_replace_entry_with(|_, _| None); - check(&m); - } - } - - #[test] - fn test_replace_entry_ref_with_doesnt_corrupt() { - #![allow(deprecated)] //rand - // Test for #19292 - fn check(m: &HashMap<std::string::String, ()>) { - for k in m.keys() { - assert!(m.contains_key(k), "{} is in keys() but not in the map?", k); - } - } - - let mut m = HashMap::new(); - - let mut rng = { - let seed = u64::from_le_bytes(*b"testseed"); - SmallRng::seed_from_u64(seed) - }; - - // Populate the map with some items. - for _ in 0..50 { - let mut x = std::string::String::with_capacity(1); - x.push(rng.gen_range('a'..='z')); - m.insert(x, ()); - } - - for _ in 0..1000 { - let mut x = std::string::String::with_capacity(1); - x.push(rng.gen_range('a'..='z')); - m.entry_ref(x.as_str()).and_replace_entry_with(|_, _| None); - check(&m); - } - } - - #[test] - fn test_retain() { - let mut map: HashMap<i32, i32> = (0..100).map(|x| (x, x * 10)).collect(); - - map.retain(|&k, _| k % 2 == 0); - assert_eq!(map.len(), 50); - assert_eq!(map[&2], 20); - assert_eq!(map[&4], 40); - assert_eq!(map[&6], 60); - } - - #[test] - fn test_drain_filter() { - { - let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect(); - let drained = map.drain_filter(|&k, _| k % 2 == 0); - let mut out = drained.collect::<Vec<_>>(); - out.sort_unstable(); - assert_eq!(vec![(0, 0), (2, 20), (4, 40), (6, 60)], out); - assert_eq!(map.len(), 4); - } - { - let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect(); - drop(map.drain_filter(|&k, _| k % 2 == 0)); - assert_eq!(map.len(), 4); - } - } - - #[test] - #[cfg_attr(miri, ignore)] // FIXME: no OOM signalling (https://github.com/rust-lang/miri/issues/613) - fn test_try_reserve() { - use crate::TryReserveError::{AllocError, CapacityOverflow}; - - const MAX_ISIZE: usize = isize::MAX as usize; - - let mut empty_bytes: HashMap<u8, u8> = HashMap::new(); - - if let Err(CapacityOverflow) = empty_bytes.try_reserve(usize::MAX) { - } else { - panic!("usize::MAX should trigger an overflow!"); - } - - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_ISIZE) { - } else { - panic!("isize::MAX should trigger an overflow!"); - } - - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_ISIZE / 5) { - } else { - // This may succeed if there is enough free memory. Attempt to - // allocate a few more hashmaps to ensure the allocation will fail. - let mut empty_bytes2: HashMap<u8, u8> = HashMap::new(); - let _ = empty_bytes2.try_reserve(MAX_ISIZE / 5); - let mut empty_bytes3: HashMap<u8, u8> = HashMap::new(); - let _ = empty_bytes3.try_reserve(MAX_ISIZE / 5); - let mut empty_bytes4: HashMap<u8, u8> = HashMap::new(); - if let Err(AllocError { .. }) = empty_bytes4.try_reserve(MAX_ISIZE / 5) { - } else { - panic!("isize::MAX / 5 should trigger an OOM!"); - } - } - } - - #[test] - fn test_raw_entry() { - use super::RawEntryMut::{Occupied, Vacant}; - - let xs = [(1_i32, 10_i32), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: HashMap<_, _> = xs.iter().copied().collect(); - - let compute_hash = |map: &HashMap<i32, i32>, k: i32| -> u64 { - super::make_insert_hash::<i32, _>(map.hasher(), &k) - }; - - // Existing key (insert) - match map.raw_entry_mut().from_key(&1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - let hash1 = compute_hash(&map, 1); - assert_eq!(map.raw_entry().from_key(&1).unwrap(), (&1, &100)); - assert_eq!( - map.raw_entry().from_hash(hash1, |k| *k == 1).unwrap(), - (&1, &100) - ); - assert_eq!( - map.raw_entry().from_key_hashed_nocheck(hash1, &1).unwrap(), - (&1, &100) - ); - assert_eq!(map.len(), 6); - - // Existing key (update) - match map.raw_entry_mut().from_key(&2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - let new_v = (*v) * 10; - *v = new_v; - } - } - let hash2 = compute_hash(&map, 2); - assert_eq!(map.raw_entry().from_key(&2).unwrap(), (&2, &200)); - assert_eq!( - map.raw_entry().from_hash(hash2, |k| *k == 2).unwrap(), - (&2, &200) - ); - assert_eq!( - map.raw_entry().from_key_hashed_nocheck(hash2, &2).unwrap(), - (&2, &200) - ); - assert_eq!(map.len(), 6); - - // Existing key (take) - let hash3 = compute_hash(&map, 3); - match map.raw_entry_mut().from_key_hashed_nocheck(hash3, &3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove_entry(), (3, 30)); - } - } - assert_eq!(map.raw_entry().from_key(&3), None); - assert_eq!(map.raw_entry().from_hash(hash3, |k| *k == 3), None); - assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash3, &3), None); - assert_eq!(map.len(), 5); - - // Nonexistent key (insert) - match map.raw_entry_mut().from_key(&10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(view.insert(10, 1000), (&mut 10, &mut 1000)); - } - } - assert_eq!(map.raw_entry().from_key(&10).unwrap(), (&10, &1000)); - assert_eq!(map.len(), 6); - - // Ensure all lookup methods produce equivalent results. - for k in 0..12 { - let hash = compute_hash(&map, k); - let v = map.get(&k).copied(); - let kv = v.as_ref().map(|v| (&k, v)); - - assert_eq!(map.raw_entry().from_key(&k), kv); - assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv); - assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv); - - match map.raw_entry_mut().from_key(&k) { - Occupied(o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - match map.raw_entry_mut().from_key_hashed_nocheck(hash, &k) { - Occupied(o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - match map.raw_entry_mut().from_hash(hash, |q| *q == k) { - Occupied(o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - } - } - - #[test] - fn test_key_without_hash_impl() { - #[derive(Debug)] - struct IntWrapper(u64); - - let mut m: HashMap<IntWrapper, (), ()> = HashMap::default(); - { - assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_none()); - } - { - let vacant_entry = match m.raw_entry_mut().from_hash(0, |k| k.0 == 0) { - RawEntryMut::Occupied(..) => panic!("Found entry for key 0"), - RawEntryMut::Vacant(e) => e, - }; - vacant_entry.insert_with_hasher(0, IntWrapper(0), (), |k| k.0); - } - { - assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_some()); - assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_none()); - assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none()); - } - { - let vacant_entry = match m.raw_entry_mut().from_hash(1, |k| k.0 == 1) { - RawEntryMut::Occupied(..) => panic!("Found entry for key 1"), - RawEntryMut::Vacant(e) => e, - }; - vacant_entry.insert_with_hasher(1, IntWrapper(1), (), |k| k.0); - } - { - assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_some()); - assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_some()); - assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none()); - } - { - let occupied_entry = match m.raw_entry_mut().from_hash(0, |k| k.0 == 0) { - RawEntryMut::Occupied(e) => e, - RawEntryMut::Vacant(..) => panic!("Couldn't find entry for key 0"), - }; - occupied_entry.remove(); - } - assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_none()); - assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_some()); - assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none()); - } - - #[test] - #[cfg(feature = "raw")] - fn test_into_iter_refresh() { - #[cfg(miri)] - const N: usize = 32; - #[cfg(not(miri))] - const N: usize = 128; - - let mut rng = rand::thread_rng(); - for n in 0..N { - let mut map = HashMap::new(); - for i in 0..n { - assert!(map.insert(i, 2 * i).is_none()); - } - let hash_builder = map.hasher().clone(); - - let mut it = unsafe { map.table.iter() }; - assert_eq!(it.len(), n); - - let mut i = 0; - let mut left = n; - let mut removed = Vec::new(); - loop { - // occasionally remove some elements - if i < n && rng.gen_bool(0.1) { - let hash_value = super::make_insert_hash(&hash_builder, &i); - - unsafe { - let e = map.table.find(hash_value, |q| q.0.eq(&i)); - if let Some(e) = e { - it.reflect_remove(&e); - let t = map.table.remove(e); - removed.push(t); - left -= 1; - } else { - assert!(removed.contains(&(i, 2 * i)), "{} not in {:?}", i, removed); - let e = map.table.insert( - hash_value, - (i, 2 * i), - super::make_hasher::<_, usize, _>(&hash_builder), - ); - it.reflect_insert(&e); - if let Some(p) = removed.iter().position(|e| e == &(i, 2 * i)) { - removed.swap_remove(p); - } - left += 1; - } - } - } - - let e = it.next(); - if e.is_none() { - break; - } - assert!(i < n); - let t = unsafe { e.unwrap().as_ref() }; - assert!(!removed.contains(t)); - let (key, value) = t; - assert_eq!(*value, 2 * key); - i += 1; - } - assert!(i <= n); - - // just for safety: - assert_eq!(map.table.len(), left); - } - } - - #[test] - fn test_const_with_hasher() { - use core::hash::BuildHasher; - use std::collections::hash_map::DefaultHasher; - - #[derive(Clone)] - struct MyHasher; - impl BuildHasher for MyHasher { - type Hasher = DefaultHasher; - - fn build_hasher(&self) -> DefaultHasher { - DefaultHasher::new() - } - } - - const EMPTY_MAP: HashMap<u32, std::string::String, MyHasher> = - HashMap::with_hasher(MyHasher); - - let mut map = EMPTY_MAP; - map.insert(17, "seventeen".to_owned()); - assert_eq!("seventeen", map[&17]); - } - - #[test] - fn test_get_each_mut() { - let mut map = HashMap::new(); - map.insert("foo".to_owned(), 0); - map.insert("bar".to_owned(), 10); - map.insert("baz".to_owned(), 20); - map.insert("qux".to_owned(), 30); - - let xs = map.get_many_mut(["foo", "qux"]); - assert_eq!(xs, Some([&mut 0, &mut 30])); - - let xs = map.get_many_mut(["foo", "dud"]); - assert_eq!(xs, None); - - let xs = map.get_many_mut(["foo", "foo"]); - assert_eq!(xs, None); - - let ys = map.get_many_key_value_mut(["bar", "baz"]); - assert_eq!( - ys, - Some([(&"bar".to_owned(), &mut 10), (&"baz".to_owned(), &mut 20),]), - ); - - let ys = map.get_many_key_value_mut(["bar", "dip"]); - assert_eq!(ys, None); - - let ys = map.get_many_key_value_mut(["baz", "baz"]); - assert_eq!(ys, None); - } - - #[test] - #[should_panic = "panic in drop"] - fn test_clone_from_double_drop() { - #[derive(Clone)] - struct CheckedDrop { - panic_in_drop: bool, - dropped: bool, - } - impl Drop for CheckedDrop { - fn drop(&mut self) { - if self.panic_in_drop { - self.dropped = true; - panic!("panic in drop"); - } - if self.dropped { - panic!("double drop"); - } - self.dropped = true; - } - } - const DISARMED: CheckedDrop = CheckedDrop { - panic_in_drop: false, - dropped: false, - }; - const ARMED: CheckedDrop = CheckedDrop { - panic_in_drop: true, - dropped: false, - }; - - let mut map1 = HashMap::new(); - map1.insert(1, DISARMED); - map1.insert(2, DISARMED); - map1.insert(3, DISARMED); - map1.insert(4, DISARMED); - - let mut map2 = HashMap::new(); - map2.insert(1, DISARMED); - map2.insert(2, ARMED); - map2.insert(3, DISARMED); - map2.insert(4, DISARMED); - - map2.clone_from(&map1); - } -} diff --git a/vendor/hashbrown-0.13.2/src/raw/alloc.rs b/vendor/hashbrown-0.13.2/src/raw/alloc.rs deleted file mode 100644 index ba09ea9de..000000000 --- a/vendor/hashbrown-0.13.2/src/raw/alloc.rs +++ /dev/null @@ -1,73 +0,0 @@ -pub(crate) use self::inner::{do_alloc, Allocator, Global}; - -#[cfg(feature = "nightly")] -mod inner { - use crate::alloc::alloc::Layout; - pub use crate::alloc::alloc::{Allocator, Global}; - use core::ptr::NonNull; - - #[allow(clippy::map_err_ignore)] - pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> { - match alloc.allocate(layout) { - Ok(ptr) => Ok(ptr.as_non_null_ptr()), - Err(_) => Err(()), - } - } - - #[cfg(feature = "bumpalo")] - unsafe impl Allocator for crate::BumpWrapper<'_> { - #[inline] - fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> { - match self.0.try_alloc_layout(layout) { - Ok(ptr) => Ok(NonNull::slice_from_raw_parts(ptr, layout.size())), - Err(_) => Err(core::alloc::AllocError), - } - } - #[inline] - unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {} - } -} - -#[cfg(not(feature = "nightly"))] -mod inner { - use crate::alloc::alloc::{alloc, dealloc, Layout}; - use core::ptr::NonNull; - - #[allow(clippy::missing_safety_doc)] // not exposed outside of this crate - pub unsafe trait Allocator { - fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()>; - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout); - } - - #[derive(Copy, Clone)] - pub struct Global; - unsafe impl Allocator for Global { - #[inline] - fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> { - unsafe { NonNull::new(alloc(layout)).ok_or(()) } - } - #[inline] - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { - dealloc(ptr.as_ptr(), layout); - } - } - impl Default for Global { - #[inline] - fn default() -> Self { - Global - } - } - - pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> { - alloc.allocate(layout) - } - - #[cfg(feature = "bumpalo")] - unsafe impl Allocator for crate::BumpWrapper<'_> { - #[allow(clippy::map_err_ignore)] - fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> { - self.0.try_alloc_layout(layout).map_err(|_| ()) - } - unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {} - } -} diff --git a/vendor/hashbrown-0.13.2/src/raw/bitmask.rs b/vendor/hashbrown-0.13.2/src/raw/bitmask.rs deleted file mode 100644 index 7d4f9fc38..000000000 --- a/vendor/hashbrown-0.13.2/src/raw/bitmask.rs +++ /dev/null @@ -1,122 +0,0 @@ -use super::imp::{BitMaskWord, BITMASK_MASK, BITMASK_STRIDE}; -#[cfg(feature = "nightly")] -use core::intrinsics; - -/// A bit mask which contains the result of a `Match` operation on a `Group` and -/// allows iterating through them. -/// -/// The bit mask is arranged so that low-order bits represent lower memory -/// addresses for group match results. -/// -/// For implementation reasons, the bits in the set may be sparsely packed, so -/// that there is only one bit-per-byte used (the high bit, 7). If this is the -/// case, `BITMASK_STRIDE` will be 8 to indicate a divide-by-8 should be -/// performed on counts/indices to normalize this difference. `BITMASK_MASK` is -/// similarly a mask of all the actually-used bits. -#[derive(Copy, Clone)] -pub struct BitMask(pub BitMaskWord); - -#[allow(clippy::use_self)] -impl BitMask { - /// Returns a new `BitMask` with all bits inverted. - #[inline] - #[must_use] - pub fn invert(self) -> Self { - BitMask(self.0 ^ BITMASK_MASK) - } - - /// Flip the bit in the mask for the entry at the given index. - /// - /// Returns the bit's previous state. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - #[cfg(feature = "raw")] - pub unsafe fn flip(&mut self, index: usize) -> bool { - // NOTE: The + BITMASK_STRIDE - 1 is to set the high bit. - let mask = 1 << (index * BITMASK_STRIDE + BITMASK_STRIDE - 1); - self.0 ^= mask; - // The bit was set if the bit is now 0. - self.0 & mask == 0 - } - - /// Returns a new `BitMask` with the lowest bit removed. - #[inline] - #[must_use] - pub fn remove_lowest_bit(self) -> Self { - BitMask(self.0 & (self.0 - 1)) - } - /// Returns whether the `BitMask` has at least one set bit. - #[inline] - pub fn any_bit_set(self) -> bool { - self.0 != 0 - } - - /// Returns the first set bit in the `BitMask`, if there is one. - #[inline] - pub fn lowest_set_bit(self) -> Option<usize> { - if self.0 == 0 { - None - } else { - Some(unsafe { self.lowest_set_bit_nonzero() }) - } - } - - /// Returns the first set bit in the `BitMask`, if there is one. The - /// bitmask must not be empty. - #[inline] - #[cfg(feature = "nightly")] - pub unsafe fn lowest_set_bit_nonzero(self) -> usize { - intrinsics::cttz_nonzero(self.0) as usize / BITMASK_STRIDE - } - #[inline] - #[cfg(not(feature = "nightly"))] - pub unsafe fn lowest_set_bit_nonzero(self) -> usize { - self.trailing_zeros() - } - - /// Returns the number of trailing zeroes in the `BitMask`. - #[inline] - pub fn trailing_zeros(self) -> usize { - // ARM doesn't have a trailing_zeroes instruction, and instead uses - // reverse_bits (RBIT) + leading_zeroes (CLZ). However older ARM - // versions (pre-ARMv7) don't have RBIT and need to emulate it - // instead. Since we only have 1 bit set in each byte on ARM, we can - // use swap_bytes (REV) + leading_zeroes instead. - if cfg!(target_arch = "arm") && BITMASK_STRIDE % 8 == 0 { - self.0.swap_bytes().leading_zeros() as usize / BITMASK_STRIDE - } else { - self.0.trailing_zeros() as usize / BITMASK_STRIDE - } - } - - /// Returns the number of leading zeroes in the `BitMask`. - #[inline] - pub fn leading_zeros(self) -> usize { - self.0.leading_zeros() as usize / BITMASK_STRIDE - } -} - -impl IntoIterator for BitMask { - type Item = usize; - type IntoIter = BitMaskIter; - - #[inline] - fn into_iter(self) -> BitMaskIter { - BitMaskIter(self) - } -} - -/// Iterator over the contents of a `BitMask`, returning the indices of set -/// bits. -pub struct BitMaskIter(BitMask); - -impl Iterator for BitMaskIter { - type Item = usize; - - #[inline] - fn next(&mut self) -> Option<usize> { - let bit = self.0.lowest_set_bit()?; - self.0 = self.0.remove_lowest_bit(); - Some(bit) - } -} diff --git a/vendor/hashbrown-0.13.2/src/raw/generic.rs b/vendor/hashbrown-0.13.2/src/raw/generic.rs deleted file mode 100644 index 52955a45b..000000000 --- a/vendor/hashbrown-0.13.2/src/raw/generic.rs +++ /dev/null @@ -1,154 +0,0 @@ -use super::bitmask::BitMask; -use super::EMPTY; -use core::{mem, ptr}; - -// Use the native word size as the group size. Using a 64-bit group size on -// a 32-bit architecture will just end up being more expensive because -// shifts and multiplies will need to be emulated. -#[cfg(any( - target_pointer_width = "64", - target_arch = "aarch64", - target_arch = "x86_64", - target_arch = "wasm32", -))] -type GroupWord = u64; -#[cfg(all( - any(target_pointer_width = "32", target_pointer_width = "16"), - not(target_arch = "aarch64"), - not(target_arch = "x86_64"), - not(target_arch = "wasm32"), -))] -type GroupWord = u32; - -pub type BitMaskWord = GroupWord; -pub const BITMASK_STRIDE: usize = 8; -// We only care about the highest bit of each byte for the mask. -#[allow(clippy::cast_possible_truncation, clippy::unnecessary_cast)] -pub const BITMASK_MASK: BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord; - -/// Helper function to replicate a byte across a `GroupWord`. -#[inline] -fn repeat(byte: u8) -> GroupWord { - GroupWord::from_ne_bytes([byte; Group::WIDTH]) -} - -/// Abstraction over a group of control bytes which can be scanned in -/// parallel. -/// -/// This implementation uses a word-sized integer. -#[derive(Copy, Clone)] -pub struct Group(GroupWord); - -// We perform all operations in the native endianness, and convert to -// little-endian just before creating a BitMask. The can potentially -// enable the compiler to eliminate unnecessary byte swaps if we are -// only checking whether a BitMask is empty. -#[allow(clippy::use_self)] -impl Group { - /// Number of bytes in the group. - pub const WIDTH: usize = mem::size_of::<Self>(); - - /// Returns a full group of empty bytes, suitable for use as the initial - /// value for an empty hash table. - /// - /// This is guaranteed to be aligned to the group size. - #[inline] - pub const fn static_empty() -> &'static [u8; Group::WIDTH] { - #[repr(C)] - struct AlignedBytes { - _align: [Group; 0], - bytes: [u8; Group::WIDTH], - } - const ALIGNED_BYTES: AlignedBytes = AlignedBytes { - _align: [], - bytes: [EMPTY; Group::WIDTH], - }; - &ALIGNED_BYTES.bytes - } - - /// Loads a group of bytes starting at the given address. - #[inline] - #[allow(clippy::cast_ptr_alignment)] // unaligned load - pub unsafe fn load(ptr: *const u8) -> Self { - Group(ptr::read_unaligned(ptr.cast())) - } - - /// Loads a group of bytes starting at the given address, which must be - /// aligned to `mem::align_of::<Group>()`. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn load_aligned(ptr: *const u8) -> Self { - // FIXME: use align_offset once it stabilizes - debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0); - Group(ptr::read(ptr.cast())) - } - - /// Stores the group of bytes to the given address, which must be - /// aligned to `mem::align_of::<Group>()`. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn store_aligned(self, ptr: *mut u8) { - // FIXME: use align_offset once it stabilizes - debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0); - ptr::write(ptr.cast(), self.0); - } - - /// Returns a `BitMask` indicating all bytes in the group which *may* - /// have the given value. - /// - /// This function may return a false positive in certain cases where - /// the byte in the group differs from the searched value only in its - /// lowest bit. This is fine because: - /// - This never happens for `EMPTY` and `DELETED`, only full entries. - /// - The check for key equality will catch these. - /// - This only happens if there is at least 1 true match. - /// - The chance of this happening is very low (< 1% chance per byte). - #[inline] - pub fn match_byte(self, byte: u8) -> BitMask { - // This algorithm is derived from - // https://graphics.stanford.edu/~seander/bithacks.html##ValueInWord - let cmp = self.0 ^ repeat(byte); - BitMask((cmp.wrapping_sub(repeat(0x01)) & !cmp & repeat(0x80)).to_le()) - } - - /// Returns a `BitMask` indicating all bytes in the group which are - /// `EMPTY`. - #[inline] - pub fn match_empty(self) -> BitMask { - // If the high bit is set, then the byte must be either: - // 1111_1111 (EMPTY) or 1000_0000 (DELETED). - // So we can just check if the top two bits are 1 by ANDing them. - BitMask((self.0 & (self.0 << 1) & repeat(0x80)).to_le()) - } - - /// Returns a `BitMask` indicating all bytes in the group which are - /// `EMPTY` or `DELETED`. - #[inline] - pub fn match_empty_or_deleted(self) -> BitMask { - // A byte is EMPTY or DELETED iff the high bit is set - BitMask((self.0 & repeat(0x80)).to_le()) - } - - /// Returns a `BitMask` indicating all bytes in the group which are full. - #[inline] - pub fn match_full(self) -> BitMask { - self.match_empty_or_deleted().invert() - } - - /// Performs the following transformation on all bytes in the group: - /// - `EMPTY => EMPTY` - /// - `DELETED => EMPTY` - /// - `FULL => DELETED` - #[inline] - pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self { - // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111 - // and high_bit = 0 (FULL) to 1000_0000 - // - // Here's this logic expanded to concrete values: - // let full = 1000_0000 (true) or 0000_0000 (false) - // !1000_0000 + 1 = 0111_1111 + 1 = 1000_0000 (no carry) - // !0000_0000 + 0 = 1111_1111 + 0 = 1111_1111 (no carry) - let full = !self.0 & repeat(0x80); - Group(!full + (full >> 7)) - } -} diff --git a/vendor/hashbrown-0.13.2/src/raw/mod.rs b/vendor/hashbrown-0.13.2/src/raw/mod.rs deleted file mode 100644 index 0e96306ef..000000000 --- a/vendor/hashbrown-0.13.2/src/raw/mod.rs +++ /dev/null @@ -1,2518 +0,0 @@ -use crate::alloc::alloc::{handle_alloc_error, Layout}; -use crate::scopeguard::{guard, ScopeGuard}; -use crate::TryReserveError; -use core::iter::FusedIterator; -use core::marker::PhantomData; -use core::mem; -use core::mem::ManuallyDrop; -use core::mem::MaybeUninit; -use core::ptr::NonNull; -use core::{hint, ptr}; - -cfg_if! { - // Use the SSE2 implementation if possible: it allows us to scan 16 buckets - // at once instead of 8. We don't bother with AVX since it would require - // runtime dispatch and wouldn't gain us much anyways: the probability of - // finding a match drops off drastically after the first few buckets. - // - // I attempted an implementation on ARM using NEON instructions, but it - // turns out that most NEON instructions have multi-cycle latency, which in - // the end outweighs any gains over the generic implementation. - if #[cfg(all( - target_feature = "sse2", - any(target_arch = "x86", target_arch = "x86_64"), - not(miri) - ))] { - mod sse2; - use sse2 as imp; - } else { - #[path = "generic.rs"] - mod generic; - use generic as imp; - } -} - -mod alloc; -pub(crate) use self::alloc::{do_alloc, Allocator, Global}; - -mod bitmask; - -use self::bitmask::{BitMask, BitMaskIter}; -use self::imp::Group; - -// Branch prediction hint. This is currently only available on nightly but it -// consistently improves performance by 10-15%. -#[cfg(feature = "nightly")] -use core::intrinsics::{likely, unlikely}; - -// On stable we can use #[cold] to get a equivalent effect: this attributes -// suggests that the function is unlikely to be called -#[cfg(not(feature = "nightly"))] -#[inline] -#[cold] -fn cold() {} - -#[cfg(not(feature = "nightly"))] -#[inline] -fn likely(b: bool) -> bool { - if !b { - cold(); - } - b -} -#[cfg(not(feature = "nightly"))] -#[inline] -fn unlikely(b: bool) -> bool { - if b { - cold(); - } - b -} - -#[inline] -unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize { - to.offset_from(from) as usize -} - -/// Whether memory allocation errors should return an error or abort. -#[derive(Copy, Clone)] -enum Fallibility { - Fallible, - Infallible, -} - -impl Fallibility { - /// Error to return on capacity overflow. - #[cfg_attr(feature = "inline-more", inline)] - fn capacity_overflow(self) -> TryReserveError { - match self { - Fallibility::Fallible => TryReserveError::CapacityOverflow, - Fallibility::Infallible => panic!("Hash table capacity overflow"), - } - } - - /// Error to return on allocation error. - #[cfg_attr(feature = "inline-more", inline)] - fn alloc_err(self, layout: Layout) -> TryReserveError { - match self { - Fallibility::Fallible => TryReserveError::AllocError { layout }, - Fallibility::Infallible => handle_alloc_error(layout), - } - } -} - -/// Control byte value for an empty bucket. -const EMPTY: u8 = 0b1111_1111; - -/// Control byte value for a deleted bucket. -const DELETED: u8 = 0b1000_0000; - -/// Checks whether a control byte represents a full bucket (top bit is clear). -#[inline] -fn is_full(ctrl: u8) -> bool { - ctrl & 0x80 == 0 -} - -/// Checks whether a control byte represents a special value (top bit is set). -#[inline] -fn is_special(ctrl: u8) -> bool { - ctrl & 0x80 != 0 -} - -/// Checks whether a special control value is EMPTY (just check 1 bit). -#[inline] -fn special_is_empty(ctrl: u8) -> bool { - debug_assert!(is_special(ctrl)); - ctrl & 0x01 != 0 -} - -/// Primary hash function, used to select the initial bucket to probe from. -#[inline] -#[allow(clippy::cast_possible_truncation)] -fn h1(hash: u64) -> usize { - // On 32-bit platforms we simply ignore the higher hash bits. - hash as usize -} - -// Constant for h2 function that grabing the top 7 bits of the hash. -const MIN_HASH_LEN: usize = if mem::size_of::<usize>() < mem::size_of::<u64>() { - mem::size_of::<usize>() -} else { - mem::size_of::<u64>() -}; - -/// Secondary hash function, saved in the low 7 bits of the control byte. -#[inline] -#[allow(clippy::cast_possible_truncation)] -fn h2(hash: u64) -> u8 { - // Grab the top 7 bits of the hash. While the hash is normally a full 64-bit - // value, some hash functions (such as FxHash) produce a usize result - // instead, which means that the top 32 bits are 0 on 32-bit platforms. - // So we use MIN_HASH_LEN constant to handle this. - let top7 = hash >> (MIN_HASH_LEN * 8 - 7); - (top7 & 0x7f) as u8 // truncation -} - -/// Probe sequence based on triangular numbers, which is guaranteed (since our -/// table size is a power of two) to visit every group of elements exactly once. -/// -/// A triangular probe has us jump by 1 more group every time. So first we -/// jump by 1 group (meaning we just continue our linear scan), then 2 groups -/// (skipping over 1 group), then 3 groups (skipping over 2 groups), and so on. -/// -/// Proof that the probe will visit every group in the table: -/// <https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/> -struct ProbeSeq { - pos: usize, - stride: usize, -} - -impl ProbeSeq { - #[inline] - fn move_next(&mut self, bucket_mask: usize) { - // We should have found an empty bucket by now and ended the probe. - debug_assert!( - self.stride <= bucket_mask, - "Went past end of probe sequence" - ); - - self.stride += Group::WIDTH; - self.pos += self.stride; - self.pos &= bucket_mask; - } -} - -/// Returns the number of buckets needed to hold the given number of items, -/// taking the maximum load factor into account. -/// -/// Returns `None` if an overflow occurs. -// Workaround for emscripten bug emscripten-core/emscripten-fastcomp#258 -#[cfg_attr(target_os = "emscripten", inline(never))] -#[cfg_attr(not(target_os = "emscripten"), inline)] -fn capacity_to_buckets(cap: usize) -> Option<usize> { - debug_assert_ne!(cap, 0); - - // For small tables we require at least 1 empty bucket so that lookups are - // guaranteed to terminate if an element doesn't exist in the table. - if cap < 8 { - // We don't bother with a table size of 2 buckets since that can only - // hold a single element. Instead we skip directly to a 4 bucket table - // which can hold 3 elements. - return Some(if cap < 4 { 4 } else { 8 }); - } - - // Otherwise require 1/8 buckets to be empty (87.5% load) - // - // Be careful when modifying this, calculate_layout relies on the - // overflow check here. - let adjusted_cap = cap.checked_mul(8)? / 7; - - // Any overflows will have been caught by the checked_mul. Also, any - // rounding errors from the division above will be cleaned up by - // next_power_of_two (which can't overflow because of the previous division). - Some(adjusted_cap.next_power_of_two()) -} - -/// Returns the maximum effective capacity for the given bucket mask, taking -/// the maximum load factor into account. -#[inline] -fn bucket_mask_to_capacity(bucket_mask: usize) -> usize { - if bucket_mask < 8 { - // For tables with 1/2/4/8 buckets, we always reserve one empty slot. - // Keep in mind that the bucket mask is one less than the bucket count. - bucket_mask - } else { - // For larger tables we reserve 12.5% of the slots as empty. - ((bucket_mask + 1) / 8) * 7 - } -} - -/// Helper which allows the max calculation for ctrl_align to be statically computed for each T -/// while keeping the rest of `calculate_layout_for` independent of `T` -#[derive(Copy, Clone)] -struct TableLayout { - size: usize, - ctrl_align: usize, -} - -impl TableLayout { - #[inline] - const fn new<T>() -> Self { - let layout = Layout::new::<T>(); - Self { - size: layout.size(), - ctrl_align: if layout.align() > Group::WIDTH { - layout.align() - } else { - Group::WIDTH - }, - } - } - - #[inline] - fn calculate_layout_for(self, buckets: usize) -> Option<(Layout, usize)> { - debug_assert!(buckets.is_power_of_two()); - - let TableLayout { size, ctrl_align } = self; - // Manual layout calculation since Layout methods are not yet stable. - let ctrl_offset = - size.checked_mul(buckets)?.checked_add(ctrl_align - 1)? & !(ctrl_align - 1); - let len = ctrl_offset.checked_add(buckets + Group::WIDTH)?; - - // We need an additional check to ensure that the allocation doesn't - // exceed `isize::MAX` (https://github.com/rust-lang/rust/pull/95295). - if len > isize::MAX as usize - (ctrl_align - 1) { - return None; - } - - Some(( - unsafe { Layout::from_size_align_unchecked(len, ctrl_align) }, - ctrl_offset, - )) - } -} - -/// A reference to a hash table bucket containing a `T`. -/// -/// This is usually just a pointer to the element itself. However if the element -/// is a ZST, then we instead track the index of the element in the table so -/// that `erase` works properly. -pub struct Bucket<T> { - // Actually it is pointer to next element than element itself - // this is needed to maintain pointer arithmetic invariants - // keeping direct pointer to element introduces difficulty. - // Using `NonNull` for variance and niche layout - ptr: NonNull<T>, -} - -// This Send impl is needed for rayon support. This is safe since Bucket is -// never exposed in a public API. -unsafe impl<T> Send for Bucket<T> {} - -impl<T> Clone for Bucket<T> { - #[inline] - fn clone(&self) -> Self { - Self { ptr: self.ptr } - } -} - -impl<T> Bucket<T> { - const IS_ZERO_SIZED_TYPE: bool = mem::size_of::<T>() == 0; - - #[inline] - unsafe fn from_base_index(base: NonNull<T>, index: usize) -> Self { - let ptr = if Self::IS_ZERO_SIZED_TYPE { - // won't overflow because index must be less than length - (index + 1) as *mut T - } else { - base.as_ptr().sub(index) - }; - Self { - ptr: NonNull::new_unchecked(ptr), - } - } - #[inline] - unsafe fn to_base_index(&self, base: NonNull<T>) -> usize { - if Self::IS_ZERO_SIZED_TYPE { - self.ptr.as_ptr() as usize - 1 - } else { - offset_from(base.as_ptr(), self.ptr.as_ptr()) - } - } - #[inline] - pub fn as_ptr(&self) -> *mut T { - if Self::IS_ZERO_SIZED_TYPE { - // Just return an arbitrary ZST pointer which is properly aligned - mem::align_of::<T>() as *mut T - } else { - unsafe { self.ptr.as_ptr().sub(1) } - } - } - #[inline] - unsafe fn next_n(&self, offset: usize) -> Self { - let ptr = if Self::IS_ZERO_SIZED_TYPE { - (self.ptr.as_ptr() as usize + offset) as *mut T - } else { - self.ptr.as_ptr().sub(offset) - }; - Self { - ptr: NonNull::new_unchecked(ptr), - } - } - #[cfg_attr(feature = "inline-more", inline)] - pub(crate) unsafe fn drop(&self) { - self.as_ptr().drop_in_place(); - } - #[inline] - pub(crate) unsafe fn read(&self) -> T { - self.as_ptr().read() - } - #[inline] - pub(crate) unsafe fn write(&self, val: T) { - self.as_ptr().write(val); - } - #[inline] - pub unsafe fn as_ref<'a>(&self) -> &'a T { - &*self.as_ptr() - } - #[inline] - pub unsafe fn as_mut<'a>(&self) -> &'a mut T { - &mut *self.as_ptr() - } - #[cfg(feature = "raw")] - #[inline] - pub unsafe fn copy_from_nonoverlapping(&self, other: &Self) { - self.as_ptr().copy_from_nonoverlapping(other.as_ptr(), 1); - } -} - -/// A raw hash table with an unsafe API. -pub struct RawTable<T, A: Allocator + Clone = Global> { - table: RawTableInner<A>, - // Tell dropck that we own instances of T. - marker: PhantomData<T>, -} - -/// Non-generic part of `RawTable` which allows functions to be instantiated only once regardless -/// of how many different key-value types are used. -struct RawTableInner<A> { - // Mask to get an index from a hash value. The value is one less than the - // number of buckets in the table. - bucket_mask: usize, - - // [Padding], T1, T2, ..., Tlast, C1, C2, ... - // ^ points here - ctrl: NonNull<u8>, - - // Number of elements that can be inserted before we need to grow the table - growth_left: usize, - - // Number of elements in the table, only really used by len() - items: usize, - - alloc: A, -} - -impl<T> RawTable<T, Global> { - /// Creates a new empty hash table without allocating any memory. - /// - /// In effect this returns a table with exactly 1 bucket. However we can - /// leave the data pointer dangling since that bucket is never written to - /// due to our load factor forcing us to always have at least 1 free bucket. - #[inline] - pub const fn new() -> Self { - Self { - table: RawTableInner::new_in(Global), - marker: PhantomData, - } - } - - /// Attempts to allocate a new hash table with at least enough capacity - /// for inserting the given number of elements without reallocating. - #[cfg(feature = "raw")] - pub fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError> { - Self::try_with_capacity_in(capacity, Global) - } - - /// Allocates a new hash table with at least enough capacity for inserting - /// the given number of elements without reallocating. - pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) - } -} - -impl<T, A: Allocator + Clone> RawTable<T, A> { - const TABLE_LAYOUT: TableLayout = TableLayout::new::<T>(); - const DATA_NEEDS_DROP: bool = mem::needs_drop::<T>(); - - /// Creates a new empty hash table without allocating any memory, using the - /// given allocator. - /// - /// In effect this returns a table with exactly 1 bucket. However we can - /// leave the data pointer dangling since that bucket is never written to - /// due to our load factor forcing us to always have at least 1 free bucket. - #[inline] - pub const fn new_in(alloc: A) -> Self { - Self { - table: RawTableInner::new_in(alloc), - marker: PhantomData, - } - } - - /// Allocates a new hash table with the given number of buckets. - /// - /// The control bytes are left uninitialized. - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn new_uninitialized( - alloc: A, - buckets: usize, - fallibility: Fallibility, - ) -> Result<Self, TryReserveError> { - debug_assert!(buckets.is_power_of_two()); - - Ok(Self { - table: RawTableInner::new_uninitialized( - alloc, - Self::TABLE_LAYOUT, - buckets, - fallibility, - )?, - marker: PhantomData, - }) - } - - /// Attempts to allocate a new hash table with at least enough capacity - /// for inserting the given number of elements without reallocating. - fn fallible_with_capacity( - alloc: A, - capacity: usize, - fallibility: Fallibility, - ) -> Result<Self, TryReserveError> { - Ok(Self { - table: RawTableInner::fallible_with_capacity( - alloc, - Self::TABLE_LAYOUT, - capacity, - fallibility, - )?, - marker: PhantomData, - }) - } - - /// Attempts to allocate a new hash table using the given allocator, with at least enough - /// capacity for inserting the given number of elements without reallocating. - #[cfg(feature = "raw")] - pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, TryReserveError> { - Self::fallible_with_capacity(alloc, capacity, Fallibility::Fallible) - } - - /// Allocates a new hash table using the given allocator, with at least enough capacity for - /// inserting the given number of elements without reallocating. - pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - // Avoid `Result::unwrap_or_else` because it bloats LLVM IR. - match Self::fallible_with_capacity(alloc, capacity, Fallibility::Infallible) { - Ok(capacity) => capacity, - Err(_) => unsafe { hint::unreachable_unchecked() }, - } - } - - /// Returns a reference to the underlying allocator. - #[inline] - pub fn allocator(&self) -> &A { - &self.table.alloc - } - - /// Deallocates the table without dropping any entries. - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn free_buckets(&mut self) { - self.table.free_buckets(Self::TABLE_LAYOUT); - } - - /// Returns pointer to one past last element of data table. - #[inline] - pub unsafe fn data_end(&self) -> NonNull<T> { - NonNull::new_unchecked(self.table.ctrl.as_ptr().cast()) - } - - /// Returns pointer to start of data table. - #[inline] - #[cfg(feature = "nightly")] - pub unsafe fn data_start(&self) -> *mut T { - self.data_end().as_ptr().wrapping_sub(self.buckets()) - } - - /// Return the information about memory allocated by the table. - /// - /// `RawTable` allocates single memory block to store both data and metadata. - /// This function returns allocation size and alignment and the beginning of the area. - /// These are the arguments which will be passed to `dealloc` when the table is dropped. - /// - /// This function might be useful for memory profiling. - #[inline] - #[cfg(feature = "raw")] - pub fn allocation_info(&self) -> (NonNull<u8>, Layout) { - self.table.allocation_info_or_zero(Self::TABLE_LAYOUT) - } - - /// Returns the index of a bucket from a `Bucket`. - #[inline] - pub unsafe fn bucket_index(&self, bucket: &Bucket<T>) -> usize { - bucket.to_base_index(self.data_end()) - } - - /// Returns a pointer to an element in the table. - #[inline] - pub unsafe fn bucket(&self, index: usize) -> Bucket<T> { - debug_assert_ne!(self.table.bucket_mask, 0); - debug_assert!(index < self.buckets()); - Bucket::from_base_index(self.data_end(), index) - } - - /// Erases an element from the table without dropping it. - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn erase_no_drop(&mut self, item: &Bucket<T>) { - let index = self.bucket_index(item); - self.table.erase(index); - } - - /// Erases an element from the table, dropping it in place. - #[cfg_attr(feature = "inline-more", inline)] - #[allow(clippy::needless_pass_by_value)] - pub unsafe fn erase(&mut self, item: Bucket<T>) { - // Erase the element from the table first since drop might panic. - self.erase_no_drop(&item); - item.drop(); - } - - /// Finds and erases an element from the table, dropping it in place. - /// Returns true if an element was found. - #[cfg(feature = "raw")] - #[cfg_attr(feature = "inline-more", inline)] - pub fn erase_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> bool { - // Avoid `Option::map` because it bloats LLVM IR. - if let Some(bucket) = self.find(hash, eq) { - unsafe { - self.erase(bucket); - } - true - } else { - false - } - } - - /// Removes an element from the table, returning it. - #[cfg_attr(feature = "inline-more", inline)] - #[allow(clippy::needless_pass_by_value)] - pub unsafe fn remove(&mut self, item: Bucket<T>) -> T { - self.erase_no_drop(&item); - item.read() - } - - /// Finds and removes an element from the table, returning it. - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<T> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.find(hash, eq) { - Some(bucket) => Some(unsafe { self.remove(bucket) }), - None => None, - } - } - - /// Marks all table buckets as empty without dropping their contents. - #[cfg_attr(feature = "inline-more", inline)] - pub fn clear_no_drop(&mut self) { - self.table.clear_no_drop(); - } - - /// Removes all elements from the table without freeing the backing memory. - #[cfg_attr(feature = "inline-more", inline)] - pub fn clear(&mut self) { - // Ensure that the table is reset even if one of the drops panic - let mut self_ = guard(self, |self_| self_.clear_no_drop()); - unsafe { - self_.drop_elements(); - } - } - - unsafe fn drop_elements(&mut self) { - if Self::DATA_NEEDS_DROP && !self.is_empty() { - for item in self.iter() { - item.drop(); - } - } - } - - /// Shrinks the table to fit `max(self.len(), min_size)` elements. - #[cfg_attr(feature = "inline-more", inline)] - pub fn shrink_to(&mut self, min_size: usize, hasher: impl Fn(&T) -> u64) { - // Calculate the minimal number of elements that we need to reserve - // space for. - let min_size = usize::max(self.table.items, min_size); - if min_size == 0 { - *self = Self::new_in(self.table.alloc.clone()); - return; - } - - // Calculate the number of buckets that we need for this number of - // elements. If the calculation overflows then the requested bucket - // count must be larger than what we have right and nothing needs to be - // done. - let min_buckets = match capacity_to_buckets(min_size) { - Some(buckets) => buckets, - None => return, - }; - - // If we have more buckets than we need, shrink the table. - if min_buckets < self.buckets() { - // Fast path if the table is empty - if self.table.items == 0 { - *self = Self::with_capacity_in(min_size, self.table.alloc.clone()); - } else { - // Avoid `Result::unwrap_or_else` because it bloats LLVM IR. - if self - .resize(min_size, hasher, Fallibility::Infallible) - .is_err() - { - unsafe { hint::unreachable_unchecked() } - } - } - } - } - - /// Ensures that at least `additional` items can be inserted into the table - /// without reallocation. - #[cfg_attr(feature = "inline-more", inline)] - pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) { - if additional > self.table.growth_left { - // Avoid `Result::unwrap_or_else` because it bloats LLVM IR. - if self - .reserve_rehash(additional, hasher, Fallibility::Infallible) - .is_err() - { - unsafe { hint::unreachable_unchecked() } - } - } - } - - /// Tries to ensure that at least `additional` items can be inserted into - /// the table without reallocation. - #[cfg_attr(feature = "inline-more", inline)] - pub fn try_reserve( - &mut self, - additional: usize, - hasher: impl Fn(&T) -> u64, - ) -> Result<(), TryReserveError> { - if additional > self.table.growth_left { - self.reserve_rehash(additional, hasher, Fallibility::Fallible) - } else { - Ok(()) - } - } - - /// Out-of-line slow path for `reserve` and `try_reserve`. - #[cold] - #[inline(never)] - fn reserve_rehash( - &mut self, - additional: usize, - hasher: impl Fn(&T) -> u64, - fallibility: Fallibility, - ) -> Result<(), TryReserveError> { - unsafe { - self.table.reserve_rehash_inner( - additional, - &|table, index| hasher(table.bucket::<T>(index).as_ref()), - fallibility, - Self::TABLE_LAYOUT, - if Self::DATA_NEEDS_DROP { - Some(mem::transmute(ptr::drop_in_place::<T> as unsafe fn(*mut T))) - } else { - None - }, - ) - } - } - - /// Allocates a new table of a different size and moves the contents of the - /// current table into it. - fn resize( - &mut self, - capacity: usize, - hasher: impl Fn(&T) -> u64, - fallibility: Fallibility, - ) -> Result<(), TryReserveError> { - unsafe { - self.table.resize_inner( - capacity, - &|table, index| hasher(table.bucket::<T>(index).as_ref()), - fallibility, - Self::TABLE_LAYOUT, - ) - } - } - - /// Inserts a new element into the table, and returns its raw bucket. - /// - /// This does not check if the given element already exists in the table. - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> { - unsafe { - let mut index = self.table.find_insert_slot(hash); - - // We can avoid growing the table once we have reached our load - // factor if we are replacing a tombstone. This works since the - // number of EMPTY slots does not change in this case. - let old_ctrl = *self.table.ctrl(index); - if unlikely(self.table.growth_left == 0 && special_is_empty(old_ctrl)) { - self.reserve(1, hasher); - index = self.table.find_insert_slot(hash); - } - - self.table.record_item_insert_at(index, old_ctrl, hash); - - let bucket = self.bucket(index); - bucket.write(value); - bucket - } - } - - /// Attempts to insert a new element without growing the table and return its raw bucket. - /// - /// Returns an `Err` containing the given element if inserting it would require growing the - /// table. - /// - /// This does not check if the given element already exists in the table. - #[cfg(feature = "raw")] - #[cfg_attr(feature = "inline-more", inline)] - pub fn try_insert_no_grow(&mut self, hash: u64, value: T) -> Result<Bucket<T>, T> { - unsafe { - match self.table.prepare_insert_no_grow(hash) { - Ok(index) => { - let bucket = self.bucket(index); - bucket.write(value); - Ok(bucket) - } - Err(()) => Err(value), - } - } - } - - /// Inserts a new element into the table, and returns a mutable reference to it. - /// - /// This does not check if the given element already exists in the table. - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert_entry(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> &mut T { - unsafe { self.insert(hash, value, hasher).as_mut() } - } - - /// Inserts a new element into the table, without growing the table. - /// - /// There must be enough space in the table to insert the new element. - /// - /// This does not check if the given element already exists in the table. - #[cfg_attr(feature = "inline-more", inline)] - #[cfg(any(feature = "raw", feature = "rustc-internal-api"))] - pub unsafe fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket<T> { - let (index, old_ctrl) = self.table.prepare_insert_slot(hash); - let bucket = self.table.bucket(index); - - // If we are replacing a DELETED entry then we don't need to update - // the load counter. - self.table.growth_left -= special_is_empty(old_ctrl) as usize; - - bucket.write(value); - self.table.items += 1; - bucket - } - - /// Temporary removes a bucket, applying the given function to the removed - /// element and optionally put back the returned value in the same bucket. - /// - /// Returns `true` if the bucket still contains an element - /// - /// This does not check if the given bucket is actually occupied. - #[cfg_attr(feature = "inline-more", inline)] - pub unsafe fn replace_bucket_with<F>(&mut self, bucket: Bucket<T>, f: F) -> bool - where - F: FnOnce(T) -> Option<T>, - { - let index = self.bucket_index(&bucket); - let old_ctrl = *self.table.ctrl(index); - debug_assert!(self.is_bucket_full(index)); - let old_growth_left = self.table.growth_left; - let item = self.remove(bucket); - if let Some(new_item) = f(item) { - self.table.growth_left = old_growth_left; - self.table.set_ctrl(index, old_ctrl); - self.table.items += 1; - self.bucket(index).write(new_item); - true - } else { - false - } - } - - /// Searches for an element in the table. - #[inline] - pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option<Bucket<T>> { - let result = self.table.find_inner(hash, &mut |index| unsafe { - eq(self.bucket(index).as_ref()) - }); - - // Avoid `Option::map` because it bloats LLVM IR. - match result { - Some(index) => Some(unsafe { self.bucket(index) }), - None => None, - } - } - - /// Gets a reference to an element in the table. - #[inline] - pub fn get(&self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&T> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.find(hash, eq) { - Some(bucket) => Some(unsafe { bucket.as_ref() }), - None => None, - } - } - - /// Gets a mutable reference to an element in the table. - #[inline] - pub fn get_mut(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&mut T> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.find(hash, eq) { - Some(bucket) => Some(unsafe { bucket.as_mut() }), - None => None, - } - } - - /// Attempts to get mutable references to `N` entries in the table at once. - /// - /// Returns an array of length `N` with the results of each query. - /// - /// At most one mutable reference will be returned to any entry. `None` will be returned if any - /// of the hashes are duplicates. `None` will be returned if the hash is not found. - /// - /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to - /// the `i`th key to be looked up. - pub fn get_many_mut<const N: usize>( - &mut self, - hashes: [u64; N], - eq: impl FnMut(usize, &T) -> bool, - ) -> Option<[&'_ mut T; N]> { - unsafe { - let ptrs = self.get_many_mut_pointers(hashes, eq)?; - - for (i, &cur) in ptrs.iter().enumerate() { - if ptrs[..i].iter().any(|&prev| ptr::eq::<T>(prev, cur)) { - return None; - } - } - // All bucket are distinct from all previous buckets so we're clear to return the result - // of the lookup. - - // TODO use `MaybeUninit::array_assume_init` here instead once that's stable. - Some(mem::transmute_copy(&ptrs)) - } - } - - pub unsafe fn get_many_unchecked_mut<const N: usize>( - &mut self, - hashes: [u64; N], - eq: impl FnMut(usize, &T) -> bool, - ) -> Option<[&'_ mut T; N]> { - let ptrs = self.get_many_mut_pointers(hashes, eq)?; - Some(mem::transmute_copy(&ptrs)) - } - - unsafe fn get_many_mut_pointers<const N: usize>( - &mut self, - hashes: [u64; N], - mut eq: impl FnMut(usize, &T) -> bool, - ) -> Option<[*mut T; N]> { - // TODO use `MaybeUninit::uninit_array` here instead once that's stable. - let mut outs: MaybeUninit<[*mut T; N]> = MaybeUninit::uninit(); - let outs_ptr = outs.as_mut_ptr(); - - for (i, &hash) in hashes.iter().enumerate() { - let cur = self.find(hash, |k| eq(i, k))?; - *(*outs_ptr).get_unchecked_mut(i) = cur.as_mut(); - } - - // TODO use `MaybeUninit::array_assume_init` here instead once that's stable. - Some(outs.assume_init()) - } - - /// Returns the number of elements the map can hold without reallocating. - /// - /// This number is a lower bound; the table might be able to hold - /// more, but is guaranteed to be able to hold at least this many. - #[inline] - pub fn capacity(&self) -> usize { - self.table.items + self.table.growth_left - } - - /// Returns the number of elements in the table. - #[inline] - pub fn len(&self) -> usize { - self.table.items - } - - /// Returns `true` if the table contains no elements. - #[inline] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Returns the number of buckets in the table. - #[inline] - pub fn buckets(&self) -> usize { - self.table.bucket_mask + 1 - } - - /// Checks whether the bucket at `index` is full. - /// - /// # Safety - /// - /// The caller must ensure `index` is less than the number of buckets. - #[inline] - pub unsafe fn is_bucket_full(&self, index: usize) -> bool { - self.table.is_bucket_full(index) - } - - /// Returns an iterator over every element in the table. It is up to - /// the caller to ensure that the `RawTable` outlives the `RawIter`. - /// Because we cannot make the `next` method unsafe on the `RawIter` - /// struct, we have to make the `iter` method unsafe. - #[inline] - pub unsafe fn iter(&self) -> RawIter<T> { - let data = Bucket::from_base_index(self.data_end(), 0); - RawIter { - iter: RawIterRange::new(self.table.ctrl.as_ptr(), data, self.table.buckets()), - items: self.table.items, - } - } - - /// Returns an iterator over occupied buckets that could match a given hash. - /// - /// `RawTable` only stores 7 bits of the hash value, so this iterator may - /// return items that have a hash value different than the one provided. You - /// should always validate the returned values before using them. - /// - /// It is up to the caller to ensure that the `RawTable` outlives the - /// `RawIterHash`. Because we cannot make the `next` method unsafe on the - /// `RawIterHash` struct, we have to make the `iter_hash` method unsafe. - #[cfg_attr(feature = "inline-more", inline)] - #[cfg(feature = "raw")] - pub unsafe fn iter_hash(&self, hash: u64) -> RawIterHash<'_, T, A> { - RawIterHash::new(self, hash) - } - - /// Returns an iterator which removes all elements from the table without - /// freeing the memory. - #[cfg_attr(feature = "inline-more", inline)] - pub fn drain(&mut self) -> RawDrain<'_, T, A> { - unsafe { - let iter = self.iter(); - self.drain_iter_from(iter) - } - } - - /// Returns an iterator which removes all elements from the table without - /// freeing the memory. - /// - /// Iteration starts at the provided iterator's current location. - /// - /// It is up to the caller to ensure that the iterator is valid for this - /// `RawTable` and covers all items that remain in the table. - #[cfg_attr(feature = "inline-more", inline)] - pub unsafe fn drain_iter_from(&mut self, iter: RawIter<T>) -> RawDrain<'_, T, A> { - debug_assert_eq!(iter.len(), self.len()); - RawDrain { - iter, - table: ManuallyDrop::new(mem::replace(self, Self::new_in(self.table.alloc.clone()))), - orig_table: NonNull::from(self), - marker: PhantomData, - } - } - - /// Returns an iterator which consumes all elements from the table. - /// - /// Iteration starts at the provided iterator's current location. - /// - /// It is up to the caller to ensure that the iterator is valid for this - /// `RawTable` and covers all items that remain in the table. - pub unsafe fn into_iter_from(self, iter: RawIter<T>) -> RawIntoIter<T, A> { - debug_assert_eq!(iter.len(), self.len()); - - let alloc = self.table.alloc.clone(); - let allocation = self.into_allocation(); - RawIntoIter { - iter, - allocation, - marker: PhantomData, - alloc, - } - } - - /// Converts the table into a raw allocation. The contents of the table - /// should be dropped using a `RawIter` before freeing the allocation. - #[cfg_attr(feature = "inline-more", inline)] - pub(crate) fn into_allocation(self) -> Option<(NonNull<u8>, Layout)> { - let alloc = if self.table.is_empty_singleton() { - None - } else { - // Avoid `Option::unwrap_or_else` because it bloats LLVM IR. - let (layout, ctrl_offset) = - match Self::TABLE_LAYOUT.calculate_layout_for(self.table.buckets()) { - Some(lco) => lco, - None => unsafe { hint::unreachable_unchecked() }, - }; - Some(( - unsafe { NonNull::new_unchecked(self.table.ctrl.as_ptr().sub(ctrl_offset)) }, - layout, - )) - }; - mem::forget(self); - alloc - } -} - -unsafe impl<T, A: Allocator + Clone> Send for RawTable<T, A> -where - T: Send, - A: Send, -{ -} -unsafe impl<T, A: Allocator + Clone> Sync for RawTable<T, A> -where - T: Sync, - A: Sync, -{ -} - -impl<A> RawTableInner<A> { - #[inline] - const fn new_in(alloc: A) -> Self { - Self { - // Be careful to cast the entire slice to a raw pointer. - ctrl: unsafe { NonNull::new_unchecked(Group::static_empty() as *const _ as *mut u8) }, - bucket_mask: 0, - items: 0, - growth_left: 0, - alloc, - } - } -} - -impl<A: Allocator + Clone> RawTableInner<A> { - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn new_uninitialized( - alloc: A, - table_layout: TableLayout, - buckets: usize, - fallibility: Fallibility, - ) -> Result<Self, TryReserveError> { - debug_assert!(buckets.is_power_of_two()); - - // Avoid `Option::ok_or_else` because it bloats LLVM IR. - let (layout, ctrl_offset) = match table_layout.calculate_layout_for(buckets) { - Some(lco) => lco, - None => return Err(fallibility.capacity_overflow()), - }; - - let ptr: NonNull<u8> = match do_alloc(&alloc, layout) { - Ok(block) => block.cast(), - Err(_) => return Err(fallibility.alloc_err(layout)), - }; - - let ctrl = NonNull::new_unchecked(ptr.as_ptr().add(ctrl_offset)); - Ok(Self { - ctrl, - bucket_mask: buckets - 1, - items: 0, - growth_left: bucket_mask_to_capacity(buckets - 1), - alloc, - }) - } - - #[inline] - fn fallible_with_capacity( - alloc: A, - table_layout: TableLayout, - capacity: usize, - fallibility: Fallibility, - ) -> Result<Self, TryReserveError> { - if capacity == 0 { - Ok(Self::new_in(alloc)) - } else { - unsafe { - let buckets = - capacity_to_buckets(capacity).ok_or_else(|| fallibility.capacity_overflow())?; - - let result = Self::new_uninitialized(alloc, table_layout, buckets, fallibility)?; - result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes()); - - Ok(result) - } - } - } - - /// Searches for an empty or deleted bucket which is suitable for inserting - /// a new element and sets the hash for that slot. - /// - /// There must be at least 1 empty bucket in the table. - #[inline] - unsafe fn prepare_insert_slot(&self, hash: u64) -> (usize, u8) { - let index = self.find_insert_slot(hash); - let old_ctrl = *self.ctrl(index); - self.set_ctrl_h2(index, hash); - (index, old_ctrl) - } - - /// Searches for an empty or deleted bucket which is suitable for inserting - /// a new element. - /// - /// There must be at least 1 empty bucket in the table. - #[inline] - fn find_insert_slot(&self, hash: u64) -> usize { - let mut probe_seq = self.probe_seq(hash); - loop { - unsafe { - let group = Group::load(self.ctrl(probe_seq.pos)); - if let Some(bit) = group.match_empty_or_deleted().lowest_set_bit() { - let result = (probe_seq.pos + bit) & self.bucket_mask; - - // In tables smaller than the group width, trailing control - // bytes outside the range of the table are filled with - // EMPTY entries. These will unfortunately trigger a - // match, but once masked may point to a full bucket that - // is already occupied. We detect this situation here and - // perform a second scan starting at the beginning of the - // table. This second scan is guaranteed to find an empty - // slot (due to the load factor) before hitting the trailing - // control bytes (containing EMPTY). - if unlikely(self.is_bucket_full(result)) { - debug_assert!(self.bucket_mask < Group::WIDTH); - debug_assert_ne!(probe_seq.pos, 0); - return Group::load_aligned(self.ctrl(0)) - .match_empty_or_deleted() - .lowest_set_bit_nonzero(); - } - - return result; - } - } - probe_seq.move_next(self.bucket_mask); - } - } - - /// Searches for an element in the table. This uses dynamic dispatch to reduce the amount of - /// code generated, but it is eliminated by LLVM optimizations. - #[inline(always)] - fn find_inner(&self, hash: u64, eq: &mut dyn FnMut(usize) -> bool) -> Option<usize> { - let h2_hash = h2(hash); - let mut probe_seq = self.probe_seq(hash); - - loop { - let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) }; - - for bit in group.match_byte(h2_hash) { - let index = (probe_seq.pos + bit) & self.bucket_mask; - - if likely(eq(index)) { - return Some(index); - } - } - - if likely(group.match_empty().any_bit_set()) { - return None; - } - - probe_seq.move_next(self.bucket_mask); - } - } - - #[allow(clippy::mut_mut)] - #[inline] - unsafe fn prepare_rehash_in_place(&mut self) { - // Bulk convert all full control bytes to DELETED, and all DELETED - // control bytes to EMPTY. This effectively frees up all buckets - // containing a DELETED entry. - for i in (0..self.buckets()).step_by(Group::WIDTH) { - let group = Group::load_aligned(self.ctrl(i)); - let group = group.convert_special_to_empty_and_full_to_deleted(); - group.store_aligned(self.ctrl(i)); - } - - // Fix up the trailing control bytes. See the comments in set_ctrl - // for the handling of tables smaller than the group width. - if self.buckets() < Group::WIDTH { - self.ctrl(0) - .copy_to(self.ctrl(Group::WIDTH), self.buckets()); - } else { - self.ctrl(0) - .copy_to(self.ctrl(self.buckets()), Group::WIDTH); - } - } - - #[inline] - unsafe fn bucket<T>(&self, index: usize) -> Bucket<T> { - debug_assert_ne!(self.bucket_mask, 0); - debug_assert!(index < self.buckets()); - Bucket::from_base_index(self.data_end(), index) - } - - #[inline] - unsafe fn bucket_ptr(&self, index: usize, size_of: usize) -> *mut u8 { - debug_assert_ne!(self.bucket_mask, 0); - debug_assert!(index < self.buckets()); - let base: *mut u8 = self.data_end().as_ptr(); - base.sub((index + 1) * size_of) - } - - #[inline] - unsafe fn data_end<T>(&self) -> NonNull<T> { - NonNull::new_unchecked(self.ctrl.as_ptr().cast()) - } - - /// Returns an iterator-like object for a probe sequence on the table. - /// - /// This iterator never terminates, but is guaranteed to visit each bucket - /// group exactly once. The loop using `probe_seq` must terminate upon - /// reaching a group containing an empty bucket. - #[inline] - fn probe_seq(&self, hash: u64) -> ProbeSeq { - ProbeSeq { - pos: h1(hash) & self.bucket_mask, - stride: 0, - } - } - - /// Returns the index of a bucket for which a value must be inserted if there is enough rooom - /// in the table, otherwise returns error - #[cfg(feature = "raw")] - #[inline] - unsafe fn prepare_insert_no_grow(&mut self, hash: u64) -> Result<usize, ()> { - let index = self.find_insert_slot(hash); - let old_ctrl = *self.ctrl(index); - if unlikely(self.growth_left == 0 && special_is_empty(old_ctrl)) { - Err(()) - } else { - self.record_item_insert_at(index, old_ctrl, hash); - Ok(index) - } - } - - #[inline] - unsafe fn record_item_insert_at(&mut self, index: usize, old_ctrl: u8, hash: u64) { - self.growth_left -= usize::from(special_is_empty(old_ctrl)); - self.set_ctrl_h2(index, hash); - self.items += 1; - } - - #[inline] - fn is_in_same_group(&self, i: usize, new_i: usize, hash: u64) -> bool { - let probe_seq_pos = self.probe_seq(hash).pos; - let probe_index = - |pos: usize| (pos.wrapping_sub(probe_seq_pos) & self.bucket_mask) / Group::WIDTH; - probe_index(i) == probe_index(new_i) - } - - /// Sets a control byte to the hash, and possibly also the replicated control byte at - /// the end of the array. - #[inline] - unsafe fn set_ctrl_h2(&self, index: usize, hash: u64) { - self.set_ctrl(index, h2(hash)); - } - - #[inline] - unsafe fn replace_ctrl_h2(&self, index: usize, hash: u64) -> u8 { - let prev_ctrl = *self.ctrl(index); - self.set_ctrl_h2(index, hash); - prev_ctrl - } - - /// Sets a control byte, and possibly also the replicated control byte at - /// the end of the array. - #[inline] - unsafe fn set_ctrl(&self, index: usize, ctrl: u8) { - // Replicate the first Group::WIDTH control bytes at the end of - // the array without using a branch: - // - If index >= Group::WIDTH then index == index2. - // - Otherwise index2 == self.bucket_mask + 1 + index. - // - // The very last replicated control byte is never actually read because - // we mask the initial index for unaligned loads, but we write it - // anyways because it makes the set_ctrl implementation simpler. - // - // If there are fewer buckets than Group::WIDTH then this code will - // replicate the buckets at the end of the trailing group. For example - // with 2 buckets and a group size of 4, the control bytes will look - // like this: - // - // Real | Replicated - // --------------------------------------------- - // | [A] | [B] | [EMPTY] | [EMPTY] | [A] | [B] | - // --------------------------------------------- - let index2 = ((index.wrapping_sub(Group::WIDTH)) & self.bucket_mask) + Group::WIDTH; - - *self.ctrl(index) = ctrl; - *self.ctrl(index2) = ctrl; - } - - /// Returns a pointer to a control byte. - #[inline] - unsafe fn ctrl(&self, index: usize) -> *mut u8 { - debug_assert!(index < self.num_ctrl_bytes()); - self.ctrl.as_ptr().add(index) - } - - #[inline] - fn buckets(&self) -> usize { - self.bucket_mask + 1 - } - - /// Checks whether the bucket at `index` is full. - /// - /// # Safety - /// - /// The caller must ensure `index` is less than the number of buckets. - #[inline] - unsafe fn is_bucket_full(&self, index: usize) -> bool { - debug_assert!(index < self.buckets()); - is_full(*self.ctrl(index)) - } - - #[inline] - fn num_ctrl_bytes(&self) -> usize { - self.bucket_mask + 1 + Group::WIDTH - } - - #[inline] - fn is_empty_singleton(&self) -> bool { - self.bucket_mask == 0 - } - - #[allow(clippy::mut_mut)] - #[inline] - unsafe fn prepare_resize( - &self, - table_layout: TableLayout, - capacity: usize, - fallibility: Fallibility, - ) -> Result<crate::scopeguard::ScopeGuard<Self, impl FnMut(&mut Self)>, TryReserveError> { - debug_assert!(self.items <= capacity); - - // Allocate and initialize the new table. - let mut new_table = RawTableInner::fallible_with_capacity( - self.alloc.clone(), - table_layout, - capacity, - fallibility, - )?; - new_table.growth_left -= self.items; - new_table.items = self.items; - - // The hash function may panic, in which case we simply free the new - // table without dropping any elements that may have been copied into - // it. - // - // This guard is also used to free the old table on success, see - // the comment at the bottom of this function. - Ok(guard(new_table, move |self_| { - if !self_.is_empty_singleton() { - self_.free_buckets(table_layout); - } - })) - } - - /// Reserves or rehashes to make room for `additional` more elements. - /// - /// This uses dynamic dispatch to reduce the amount of - /// code generated, but it is eliminated by LLVM optimizations when inlined. - #[allow(clippy::inline_always)] - #[inline(always)] - unsafe fn reserve_rehash_inner( - &mut self, - additional: usize, - hasher: &dyn Fn(&mut Self, usize) -> u64, - fallibility: Fallibility, - layout: TableLayout, - drop: Option<fn(*mut u8)>, - ) -> Result<(), TryReserveError> { - // Avoid `Option::ok_or_else` because it bloats LLVM IR. - let new_items = match self.items.checked_add(additional) { - Some(new_items) => new_items, - None => return Err(fallibility.capacity_overflow()), - }; - let full_capacity = bucket_mask_to_capacity(self.bucket_mask); - if new_items <= full_capacity / 2 { - // Rehash in-place without re-allocating if we have plenty of spare - // capacity that is locked up due to DELETED entries. - self.rehash_in_place(hasher, layout.size, drop); - Ok(()) - } else { - // Otherwise, conservatively resize to at least the next size up - // to avoid churning deletes into frequent rehashes. - self.resize_inner( - usize::max(new_items, full_capacity + 1), - hasher, - fallibility, - layout, - ) - } - } - - /// Allocates a new table of a different size and moves the contents of the - /// current table into it. - /// - /// This uses dynamic dispatch to reduce the amount of - /// code generated, but it is eliminated by LLVM optimizations when inlined. - #[allow(clippy::inline_always)] - #[inline(always)] - unsafe fn resize_inner( - &mut self, - capacity: usize, - hasher: &dyn Fn(&mut Self, usize) -> u64, - fallibility: Fallibility, - layout: TableLayout, - ) -> Result<(), TryReserveError> { - let mut new_table = self.prepare_resize(layout, capacity, fallibility)?; - - // Copy all elements to the new table. - for i in 0..self.buckets() { - if !self.is_bucket_full(i) { - continue; - } - - // This may panic. - let hash = hasher(self, i); - - // We can use a simpler version of insert() here since: - // - there are no DELETED entries. - // - we know there is enough space in the table. - // - all elements are unique. - let (index, _) = new_table.prepare_insert_slot(hash); - - ptr::copy_nonoverlapping( - self.bucket_ptr(i, layout.size), - new_table.bucket_ptr(index, layout.size), - layout.size, - ); - } - - // We successfully copied all elements without panicking. Now replace - // self with the new table. The old table will have its memory freed but - // the items will not be dropped (since they have been moved into the - // new table). - mem::swap(self, &mut new_table); - - Ok(()) - } - - /// Rehashes the contents of the table in place (i.e. without changing the - /// allocation). - /// - /// If `hasher` panics then some the table's contents may be lost. - /// - /// This uses dynamic dispatch to reduce the amount of - /// code generated, but it is eliminated by LLVM optimizations when inlined. - #[allow(clippy::inline_always)] - #[cfg_attr(feature = "inline-more", inline(always))] - #[cfg_attr(not(feature = "inline-more"), inline)] - unsafe fn rehash_in_place( - &mut self, - hasher: &dyn Fn(&mut Self, usize) -> u64, - size_of: usize, - drop: Option<fn(*mut u8)>, - ) { - // If the hash function panics then properly clean up any elements - // that we haven't rehashed yet. We unfortunately can't preserve the - // element since we lost their hash and have no way of recovering it - // without risking another panic. - self.prepare_rehash_in_place(); - - let mut guard = guard(self, move |self_| { - if let Some(drop) = drop { - for i in 0..self_.buckets() { - if *self_.ctrl(i) == DELETED { - self_.set_ctrl(i, EMPTY); - drop(self_.bucket_ptr(i, size_of)); - self_.items -= 1; - } - } - } - self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items; - }); - - // At this point, DELETED elements are elements that we haven't - // rehashed yet. Find them and re-insert them at their ideal - // position. - 'outer: for i in 0..guard.buckets() { - if *guard.ctrl(i) != DELETED { - continue; - } - - let i_p = guard.bucket_ptr(i, size_of); - - 'inner: loop { - // Hash the current item - let hash = hasher(*guard, i); - - // Search for a suitable place to put it - let new_i = guard.find_insert_slot(hash); - - // Probing works by scanning through all of the control - // bytes in groups, which may not be aligned to the group - // size. If both the new and old position fall within the - // same unaligned group, then there is no benefit in moving - // it and we can just continue to the next item. - if likely(guard.is_in_same_group(i, new_i, hash)) { - guard.set_ctrl_h2(i, hash); - continue 'outer; - } - - let new_i_p = guard.bucket_ptr(new_i, size_of); - - // We are moving the current item to a new position. Write - // our H2 to the control byte of the new position. - let prev_ctrl = guard.replace_ctrl_h2(new_i, hash); - if prev_ctrl == EMPTY { - guard.set_ctrl(i, EMPTY); - // If the target slot is empty, simply move the current - // element into the new slot and clear the old control - // byte. - ptr::copy_nonoverlapping(i_p, new_i_p, size_of); - continue 'outer; - } else { - // If the target slot is occupied, swap the two elements - // and then continue processing the element that we just - // swapped into the old slot. - debug_assert_eq!(prev_ctrl, DELETED); - ptr::swap_nonoverlapping(i_p, new_i_p, size_of); - continue 'inner; - } - } - } - - guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items; - - mem::forget(guard); - } - - #[inline] - unsafe fn free_buckets(&mut self, table_layout: TableLayout) { - let (ptr, layout) = self.allocation_info(table_layout); - self.alloc.deallocate(ptr, layout); - } - - #[inline] - fn allocation_info(&self, table_layout: TableLayout) -> (NonNull<u8>, Layout) { - debug_assert!( - !self.is_empty_singleton(), - "this function can only be called on non-empty tables" - ); - - // Avoid `Option::unwrap_or_else` because it bloats LLVM IR. - let (layout, ctrl_offset) = match table_layout.calculate_layout_for(self.buckets()) { - Some(lco) => lco, - None => unsafe { hint::unreachable_unchecked() }, - }; - ( - unsafe { NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)) }, - layout, - ) - } - - #[cfg(feature = "raw")] - fn allocation_info_or_zero(&self, table_layout: TableLayout) -> (NonNull<u8>, Layout) { - if self.is_empty_singleton() { - (NonNull::dangling(), Layout::new::<()>()) - } else { - self.allocation_info(table_layout) - } - } - - /// Marks all table buckets as empty without dropping their contents. - #[inline] - fn clear_no_drop(&mut self) { - if !self.is_empty_singleton() { - unsafe { - self.ctrl(0).write_bytes(EMPTY, self.num_ctrl_bytes()); - } - } - self.items = 0; - self.growth_left = bucket_mask_to_capacity(self.bucket_mask); - } - - #[inline] - unsafe fn erase(&mut self, index: usize) { - debug_assert!(self.is_bucket_full(index)); - let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask; - let empty_before = Group::load(self.ctrl(index_before)).match_empty(); - let empty_after = Group::load(self.ctrl(index)).match_empty(); - - // If we are inside a continuous block of Group::WIDTH full or deleted - // cells then a probe window may have seen a full block when trying to - // insert. We therefore need to keep that block non-empty so that - // lookups will continue searching to the next probe window. - // - // Note that in this context `leading_zeros` refers to the bytes at the - // end of a group, while `trailing_zeros` refers to the bytes at the - // beginning of a group. - let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH { - DELETED - } else { - self.growth_left += 1; - EMPTY - }; - self.set_ctrl(index, ctrl); - self.items -= 1; - } -} - -impl<T: Clone, A: Allocator + Clone> Clone for RawTable<T, A> { - fn clone(&self) -> Self { - if self.table.is_empty_singleton() { - Self::new_in(self.table.alloc.clone()) - } else { - unsafe { - // Avoid `Result::ok_or_else` because it bloats LLVM IR. - let new_table = match Self::new_uninitialized( - self.table.alloc.clone(), - self.table.buckets(), - Fallibility::Infallible, - ) { - Ok(table) => table, - Err(_) => hint::unreachable_unchecked(), - }; - - // If cloning fails then we need to free the allocation for the - // new table. However we don't run its drop since its control - // bytes are not initialized yet. - let mut guard = guard(ManuallyDrop::new(new_table), |new_table| { - new_table.free_buckets(); - }); - - guard.clone_from_spec(self); - - // Disarm the scope guard and return the newly created table. - ManuallyDrop::into_inner(ScopeGuard::into_inner(guard)) - } - } - } - - fn clone_from(&mut self, source: &Self) { - if source.table.is_empty_singleton() { - *self = Self::new_in(self.table.alloc.clone()); - } else { - unsafe { - // Make sure that if any panics occurs, we clear the table and - // leave it in an empty state. - let mut self_ = guard(self, |self_| { - self_.clear_no_drop(); - }); - - // First, drop all our elements without clearing the control - // bytes. If this panics then the scope guard will clear the - // table, leaking any elements that were not dropped yet. - // - // This leak is unavoidable: we can't try dropping more elements - // since this could lead to another panic and abort the process. - self_.drop_elements(); - - // If necessary, resize our table to match the source. - if self_.buckets() != source.buckets() { - // Skip our drop by using ptr::write. - if !self_.table.is_empty_singleton() { - self_.free_buckets(); - } - (&mut **self_ as *mut Self).write( - // Avoid `Result::unwrap_or_else` because it bloats LLVM IR. - match Self::new_uninitialized( - self_.table.alloc.clone(), - source.buckets(), - Fallibility::Infallible, - ) { - Ok(table) => table, - Err(_) => hint::unreachable_unchecked(), - }, - ); - } - - self_.clone_from_spec(source); - - // Disarm the scope guard if cloning was successful. - ScopeGuard::into_inner(self_); - } - } - } -} - -/// Specialization of `clone_from` for `Copy` types -trait RawTableClone { - unsafe fn clone_from_spec(&mut self, source: &Self); -} -impl<T: Clone, A: Allocator + Clone> RawTableClone for RawTable<T, A> { - default_fn! { - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn clone_from_spec(&mut self, source: &Self) { - self.clone_from_impl(source); - } - } -} -#[cfg(feature = "nightly")] -impl<T: Copy, A: Allocator + Clone> RawTableClone for RawTable<T, A> { - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn clone_from_spec(&mut self, source: &Self) { - source - .table - .ctrl(0) - .copy_to_nonoverlapping(self.table.ctrl(0), self.table.num_ctrl_bytes()); - source - .data_start() - .copy_to_nonoverlapping(self.data_start(), self.table.buckets()); - - self.table.items = source.table.items; - self.table.growth_left = source.table.growth_left; - } -} - -impl<T: Clone, A: Allocator + Clone> RawTable<T, A> { - /// Common code for clone and clone_from. Assumes: - /// - `self.buckets() == source.buckets()`. - /// - Any existing elements have been dropped. - /// - The control bytes are not initialized yet. - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn clone_from_impl(&mut self, source: &Self) { - // Copy the control bytes unchanged. We do this in a single pass - source - .table - .ctrl(0) - .copy_to_nonoverlapping(self.table.ctrl(0), self.table.num_ctrl_bytes()); - - // The cloning of elements may panic, in which case we need - // to make sure we drop only the elements that have been - // cloned so far. - let mut guard = guard((0, &mut *self), |(index, self_)| { - if Self::DATA_NEEDS_DROP && !self_.is_empty() { - for i in 0..=*index { - if self_.is_bucket_full(i) { - self_.bucket(i).drop(); - } - } - } - }); - - for from in source.iter() { - let index = source.bucket_index(&from); - let to = guard.1.bucket(index); - to.write(from.as_ref().clone()); - - // Update the index in case we need to unwind. - guard.0 = index; - } - - // Successfully cloned all items, no need to clean up. - mem::forget(guard); - - self.table.items = source.table.items; - self.table.growth_left = source.table.growth_left; - } - - /// Variant of `clone_from` to use when a hasher is available. - #[cfg(feature = "raw")] - pub fn clone_from_with_hasher(&mut self, source: &Self, hasher: impl Fn(&T) -> u64) { - // If we have enough capacity in the table, just clear it and insert - // elements one by one. We don't do this if we have the same number of - // buckets as the source since we can just copy the contents directly - // in that case. - if self.table.buckets() != source.table.buckets() - && bucket_mask_to_capacity(self.table.bucket_mask) >= source.len() - { - self.clear(); - - let guard_self = guard(&mut *self, |self_| { - // Clear the partially copied table if a panic occurs, otherwise - // items and growth_left will be out of sync with the contents - // of the table. - self_.clear(); - }); - - unsafe { - for item in source.iter() { - // This may panic. - let item = item.as_ref().clone(); - let hash = hasher(&item); - - // We can use a simpler version of insert() here since: - // - there are no DELETED entries. - // - we know there is enough space in the table. - // - all elements are unique. - let (index, _) = guard_self.table.prepare_insert_slot(hash); - guard_self.bucket(index).write(item); - } - } - - // Successfully cloned all items, no need to clean up. - mem::forget(guard_self); - - self.table.items = source.table.items; - self.table.growth_left -= source.table.items; - } else { - self.clone_from(source); - } - } -} - -impl<T, A: Allocator + Clone + Default> Default for RawTable<T, A> { - #[inline] - fn default() -> Self { - Self::new_in(Default::default()) - } -} - -#[cfg(feature = "nightly")] -unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawTable<T, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - if !self.table.is_empty_singleton() { - unsafe { - self.drop_elements(); - self.free_buckets(); - } - } - } -} -#[cfg(not(feature = "nightly"))] -impl<T, A: Allocator + Clone> Drop for RawTable<T, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - if !self.table.is_empty_singleton() { - unsafe { - self.drop_elements(); - self.free_buckets(); - } - } - } -} - -impl<T, A: Allocator + Clone> IntoIterator for RawTable<T, A> { - type Item = T; - type IntoIter = RawIntoIter<T, A>; - - #[cfg_attr(feature = "inline-more", inline)] - fn into_iter(self) -> RawIntoIter<T, A> { - unsafe { - let iter = self.iter(); - self.into_iter_from(iter) - } - } -} - -/// Iterator over a sub-range of a table. Unlike `RawIter` this iterator does -/// not track an item count. -pub(crate) struct RawIterRange<T> { - // Mask of full buckets in the current group. Bits are cleared from this - // mask as each element is processed. - current_group: BitMask, - - // Pointer to the buckets for the current group. - data: Bucket<T>, - - // Pointer to the next group of control bytes, - // Must be aligned to the group size. - next_ctrl: *const u8, - - // Pointer one past the last control byte of this range. - end: *const u8, -} - -impl<T> RawIterRange<T> { - /// Returns a `RawIterRange` covering a subset of a table. - /// - /// The control byte address must be aligned to the group size. - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn new(ctrl: *const u8, data: Bucket<T>, len: usize) -> Self { - debug_assert_ne!(len, 0); - debug_assert_eq!(ctrl as usize % Group::WIDTH, 0); - let end = ctrl.add(len); - - // Load the first group and advance ctrl to point to the next group - let current_group = Group::load_aligned(ctrl).match_full(); - let next_ctrl = ctrl.add(Group::WIDTH); - - Self { - current_group, - data, - next_ctrl, - end, - } - } - - /// Splits a `RawIterRange` into two halves. - /// - /// Returns `None` if the remaining range is smaller than or equal to the - /// group width. - #[cfg_attr(feature = "inline-more", inline)] - #[cfg(feature = "rayon")] - pub(crate) fn split(mut self) -> (Self, Option<RawIterRange<T>>) { - unsafe { - if self.end <= self.next_ctrl { - // Nothing to split if the group that we are current processing - // is the last one. - (self, None) - } else { - // len is the remaining number of elements after the group that - // we are currently processing. It must be a multiple of the - // group size (small tables are caught by the check above). - let len = offset_from(self.end, self.next_ctrl); - debug_assert_eq!(len % Group::WIDTH, 0); - - // Split the remaining elements into two halves, but round the - // midpoint down in case there is an odd number of groups - // remaining. This ensures that: - // - The tail is at least 1 group long. - // - The split is roughly even considering we still have the - // current group to process. - let mid = (len / 2) & !(Group::WIDTH - 1); - - let tail = Self::new( - self.next_ctrl.add(mid), - self.data.next_n(Group::WIDTH).next_n(mid), - len - mid, - ); - debug_assert_eq!( - self.data.next_n(Group::WIDTH).next_n(mid).ptr, - tail.data.ptr - ); - debug_assert_eq!(self.end, tail.end); - self.end = self.next_ctrl.add(mid); - debug_assert_eq!(self.end.add(Group::WIDTH), tail.next_ctrl); - (self, Some(tail)) - } - } - } - - /// # Safety - /// If DO_CHECK_PTR_RANGE is false, caller must ensure that we never try to iterate - /// after yielding all elements. - #[cfg_attr(feature = "inline-more", inline)] - unsafe fn next_impl<const DO_CHECK_PTR_RANGE: bool>(&mut self) -> Option<Bucket<T>> { - loop { - if let Some(index) = self.current_group.lowest_set_bit() { - self.current_group = self.current_group.remove_lowest_bit(); - return Some(self.data.next_n(index)); - } - - if DO_CHECK_PTR_RANGE && self.next_ctrl >= self.end { - return None; - } - - // We might read past self.end up to the next group boundary, - // but this is fine because it only occurs on tables smaller - // than the group size where the trailing control bytes are all - // EMPTY. On larger tables self.end is guaranteed to be aligned - // to the group size (since tables are power-of-two sized). - self.current_group = Group::load_aligned(self.next_ctrl).match_full(); - self.data = self.data.next_n(Group::WIDTH); - self.next_ctrl = self.next_ctrl.add(Group::WIDTH); - } - } -} - -// We make raw iterators unconditionally Send and Sync, and let the PhantomData -// in the actual iterator implementations determine the real Send/Sync bounds. -unsafe impl<T> Send for RawIterRange<T> {} -unsafe impl<T> Sync for RawIterRange<T> {} - -impl<T> Clone for RawIterRange<T> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Self { - data: self.data.clone(), - next_ctrl: self.next_ctrl, - current_group: self.current_group, - end: self.end, - } - } -} - -impl<T> Iterator for RawIterRange<T> { - type Item = Bucket<T>; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<Bucket<T>> { - unsafe { - // SAFETY: We set checker flag to true. - self.next_impl::<true>() - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - // We don't have an item count, so just guess based on the range size. - let remaining_buckets = if self.end > self.next_ctrl { - unsafe { offset_from(self.end, self.next_ctrl) } - } else { - 0 - }; - - // Add a group width to include the group we are currently processing. - (0, Some(Group::WIDTH + remaining_buckets)) - } -} - -impl<T> FusedIterator for RawIterRange<T> {} - -/// Iterator which returns a raw pointer to every full bucket in the table. -/// -/// For maximum flexibility this iterator is not bound by a lifetime, but you -/// must observe several rules when using it: -/// - You must not free the hash table while iterating (including via growing/shrinking). -/// - It is fine to erase a bucket that has been yielded by the iterator. -/// - Erasing a bucket that has not yet been yielded by the iterator may still -/// result in the iterator yielding that bucket (unless `reflect_remove` is called). -/// - It is unspecified whether an element inserted after the iterator was -/// created will be yielded by that iterator (unless `reflect_insert` is called). -/// - The order in which the iterator yields bucket is unspecified and may -/// change in the future. -pub struct RawIter<T> { - pub(crate) iter: RawIterRange<T>, - items: usize, -} - -impl<T> RawIter<T> { - const DATA_NEEDS_DROP: bool = mem::needs_drop::<T>(); - - /// Refresh the iterator so that it reflects a removal from the given bucket. - /// - /// For the iterator to remain valid, this method must be called once - /// for each removed bucket before `next` is called again. - /// - /// This method should be called _before_ the removal is made. It is not necessary to call this - /// method if you are removing an item that this iterator yielded in the past. - #[cfg(feature = "raw")] - pub fn reflect_remove(&mut self, b: &Bucket<T>) { - self.reflect_toggle_full(b, false); - } - - /// Refresh the iterator so that it reflects an insertion into the given bucket. - /// - /// For the iterator to remain valid, this method must be called once - /// for each insert before `next` is called again. - /// - /// This method does not guarantee that an insertion of a bucket with a greater - /// index than the last one yielded will be reflected in the iterator. - /// - /// This method should be called _after_ the given insert is made. - #[cfg(feature = "raw")] - pub fn reflect_insert(&mut self, b: &Bucket<T>) { - self.reflect_toggle_full(b, true); - } - - /// Refresh the iterator so that it reflects a change to the state of the given bucket. - #[cfg(feature = "raw")] - fn reflect_toggle_full(&mut self, b: &Bucket<T>, is_insert: bool) { - unsafe { - if b.as_ptr() > self.iter.data.as_ptr() { - // The iterator has already passed the bucket's group. - // So the toggle isn't relevant to this iterator. - return; - } - - if self.iter.next_ctrl < self.iter.end - && b.as_ptr() <= self.iter.data.next_n(Group::WIDTH).as_ptr() - { - // The iterator has not yet reached the bucket's group. - // We don't need to reload anything, but we do need to adjust the item count. - - if cfg!(debug_assertions) { - // Double-check that the user isn't lying to us by checking the bucket state. - // To do that, we need to find its control byte. We know that self.iter.data is - // at self.iter.next_ctrl - Group::WIDTH, so we work from there: - let offset = offset_from(self.iter.data.as_ptr(), b.as_ptr()); - let ctrl = self.iter.next_ctrl.sub(Group::WIDTH).add(offset); - // This method should be called _before_ a removal, or _after_ an insert, - // so in both cases the ctrl byte should indicate that the bucket is full. - assert!(is_full(*ctrl)); - } - - if is_insert { - self.items += 1; - } else { - self.items -= 1; - } - - return; - } - - // The iterator is at the bucket group that the toggled bucket is in. - // We need to do two things: - // - // - Determine if the iterator already yielded the toggled bucket. - // If it did, we're done. - // - Otherwise, update the iterator cached group so that it won't - // yield a to-be-removed bucket, or _will_ yield a to-be-added bucket. - // We'll also need to update the item count accordingly. - if let Some(index) = self.iter.current_group.lowest_set_bit() { - let next_bucket = self.iter.data.next_n(index); - if b.as_ptr() > next_bucket.as_ptr() { - // The toggled bucket is "before" the bucket the iterator would yield next. We - // therefore don't need to do anything --- the iterator has already passed the - // bucket in question. - // - // The item count must already be correct, since a removal or insert "prior" to - // the iterator's position wouldn't affect the item count. - } else { - // The removed bucket is an upcoming bucket. We need to make sure it does _not_ - // get yielded, and also that it's no longer included in the item count. - // - // NOTE: We can't just reload the group here, both since that might reflect - // inserts we've already passed, and because that might inadvertently unset the - // bits for _other_ removals. If we do that, we'd have to also decrement the - // item count for those other bits that we unset. But the presumably subsequent - // call to reflect for those buckets might _also_ decrement the item count. - // Instead, we _just_ flip the bit for the particular bucket the caller asked - // us to reflect. - let our_bit = offset_from(self.iter.data.as_ptr(), b.as_ptr()); - let was_full = self.iter.current_group.flip(our_bit); - debug_assert_ne!(was_full, is_insert); - - if is_insert { - self.items += 1; - } else { - self.items -= 1; - } - - if cfg!(debug_assertions) { - if b.as_ptr() == next_bucket.as_ptr() { - // The removed bucket should no longer be next - debug_assert_ne!(self.iter.current_group.lowest_set_bit(), Some(index)); - } else { - // We should not have changed what bucket comes next. - debug_assert_eq!(self.iter.current_group.lowest_set_bit(), Some(index)); - } - } - } - } else { - // We must have already iterated past the removed item. - } - } - } - - unsafe fn drop_elements(&mut self) { - if Self::DATA_NEEDS_DROP && self.len() != 0 { - for item in self { - item.drop(); - } - } - } -} - -impl<T> Clone for RawIter<T> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Self { - iter: self.iter.clone(), - items: self.items, - } - } -} - -impl<T> Iterator for RawIter<T> { - type Item = Bucket<T>; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<Bucket<T>> { - // Inner iterator iterates over buckets - // so it can do unnecessary work if we already yielded all items. - if self.items == 0 { - return None; - } - - let nxt = unsafe { - // SAFETY: We check number of items to yield using `items` field. - self.iter.next_impl::<false>() - }; - - if nxt.is_some() { - self.items -= 1; - } - - nxt - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - (self.items, Some(self.items)) - } -} - -impl<T> ExactSizeIterator for RawIter<T> {} -impl<T> FusedIterator for RawIter<T> {} - -/// Iterator which consumes a table and returns elements. -pub struct RawIntoIter<T, A: Allocator + Clone = Global> { - iter: RawIter<T>, - allocation: Option<(NonNull<u8>, Layout)>, - marker: PhantomData<T>, - alloc: A, -} - -impl<T, A: Allocator + Clone> RawIntoIter<T, A> { - #[cfg_attr(feature = "inline-more", inline)] - pub fn iter(&self) -> RawIter<T> { - self.iter.clone() - } -} - -unsafe impl<T, A: Allocator + Clone> Send for RawIntoIter<T, A> -where - T: Send, - A: Send, -{ -} -unsafe impl<T, A: Allocator + Clone> Sync for RawIntoIter<T, A> -where - T: Sync, - A: Sync, -{ -} - -#[cfg(feature = "nightly")] -unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawIntoIter<T, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - unsafe { - // Drop all remaining elements - self.iter.drop_elements(); - - // Free the table - if let Some((ptr, layout)) = self.allocation { - self.alloc.deallocate(ptr, layout); - } - } - } -} -#[cfg(not(feature = "nightly"))] -impl<T, A: Allocator + Clone> Drop for RawIntoIter<T, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - unsafe { - // Drop all remaining elements - self.iter.drop_elements(); - - // Free the table - if let Some((ptr, layout)) = self.allocation { - self.alloc.deallocate(ptr, layout); - } - } - } -} - -impl<T, A: Allocator + Clone> Iterator for RawIntoIter<T, A> { - type Item = T; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<T> { - unsafe { Some(self.iter.next()?.read()) } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -impl<T, A: Allocator + Clone> ExactSizeIterator for RawIntoIter<T, A> {} -impl<T, A: Allocator + Clone> FusedIterator for RawIntoIter<T, A> {} - -/// Iterator which consumes elements without freeing the table storage. -pub struct RawDrain<'a, T, A: Allocator + Clone = Global> { - iter: RawIter<T>, - - // The table is moved into the iterator for the duration of the drain. This - // ensures that an empty table is left if the drain iterator is leaked - // without dropping. - table: ManuallyDrop<RawTable<T, A>>, - orig_table: NonNull<RawTable<T, A>>, - - // We don't use a &'a mut RawTable<T> because we want RawDrain to be - // covariant over T. - marker: PhantomData<&'a RawTable<T, A>>, -} - -impl<T, A: Allocator + Clone> RawDrain<'_, T, A> { - #[cfg_attr(feature = "inline-more", inline)] - pub fn iter(&self) -> RawIter<T> { - self.iter.clone() - } -} - -unsafe impl<T, A: Allocator + Copy> Send for RawDrain<'_, T, A> -where - T: Send, - A: Send, -{ -} -unsafe impl<T, A: Allocator + Copy> Sync for RawDrain<'_, T, A> -where - T: Sync, - A: Sync, -{ -} - -impl<T, A: Allocator + Clone> Drop for RawDrain<'_, T, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - unsafe { - // Drop all remaining elements. Note that this may panic. - self.iter.drop_elements(); - - // Reset the contents of the table now that all elements have been - // dropped. - self.table.clear_no_drop(); - - // Move the now empty table back to its original location. - self.orig_table - .as_ptr() - .copy_from_nonoverlapping(&*self.table, 1); - } - } -} - -impl<T, A: Allocator + Clone> Iterator for RawDrain<'_, T, A> { - type Item = T; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<T> { - unsafe { - let item = self.iter.next()?; - Some(item.read()) - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -impl<T, A: Allocator + Clone> ExactSizeIterator for RawDrain<'_, T, A> {} -impl<T, A: Allocator + Clone> FusedIterator for RawDrain<'_, T, A> {} - -/// Iterator over occupied buckets that could match a given hash. -/// -/// `RawTable` only stores 7 bits of the hash value, so this iterator may return -/// items that have a hash value different than the one provided. You should -/// always validate the returned values before using them. -pub struct RawIterHash<'a, T, A: Allocator + Clone = Global> { - inner: RawIterHashInner<'a, A>, - _marker: PhantomData<T>, -} - -struct RawIterHashInner<'a, A: Allocator + Clone> { - table: &'a RawTableInner<A>, - - // The top 7 bits of the hash. - h2_hash: u8, - - // The sequence of groups to probe in the search. - probe_seq: ProbeSeq, - - group: Group, - - // The elements within the group with a matching h2-hash. - bitmask: BitMaskIter, -} - -impl<'a, T, A: Allocator + Clone> RawIterHash<'a, T, A> { - #[cfg_attr(feature = "inline-more", inline)] - #[cfg(feature = "raw")] - fn new(table: &'a RawTable<T, A>, hash: u64) -> Self { - RawIterHash { - inner: RawIterHashInner::new(&table.table, hash), - _marker: PhantomData, - } - } -} -impl<'a, A: Allocator + Clone> RawIterHashInner<'a, A> { - #[cfg_attr(feature = "inline-more", inline)] - #[cfg(feature = "raw")] - fn new(table: &'a RawTableInner<A>, hash: u64) -> Self { - unsafe { - let h2_hash = h2(hash); - let probe_seq = table.probe_seq(hash); - let group = Group::load(table.ctrl(probe_seq.pos)); - let bitmask = group.match_byte(h2_hash).into_iter(); - - RawIterHashInner { - table, - h2_hash, - probe_seq, - group, - bitmask, - } - } - } -} - -impl<'a, T, A: Allocator + Clone> Iterator for RawIterHash<'a, T, A> { - type Item = Bucket<T>; - - fn next(&mut self) -> Option<Bucket<T>> { - unsafe { - match self.inner.next() { - Some(index) => Some(self.inner.table.bucket(index)), - None => None, - } - } - } -} - -impl<'a, A: Allocator + Clone> Iterator for RawIterHashInner<'a, A> { - type Item = usize; - - fn next(&mut self) -> Option<Self::Item> { - unsafe { - loop { - if let Some(bit) = self.bitmask.next() { - let index = (self.probe_seq.pos + bit) & self.table.bucket_mask; - return Some(index); - } - if likely(self.group.match_empty().any_bit_set()) { - return None; - } - self.probe_seq.move_next(self.table.bucket_mask); - self.group = Group::load(self.table.ctrl(self.probe_seq.pos)); - self.bitmask = self.group.match_byte(self.h2_hash).into_iter(); - } - } - } -} - -#[cfg(test)] -mod test_map { - use super::*; - - fn rehash_in_place<T>(table: &mut RawTable<T>, hasher: impl Fn(&T) -> u64) { - unsafe { - table.table.rehash_in_place( - &|table, index| hasher(table.bucket::<T>(index).as_ref()), - mem::size_of::<T>(), - if mem::needs_drop::<T>() { - Some(mem::transmute(ptr::drop_in_place::<T> as unsafe fn(*mut T))) - } else { - None - }, - ); - } - } - - #[test] - fn rehash() { - let mut table = RawTable::new(); - let hasher = |i: &u64| *i; - for i in 0..100 { - table.insert(i, i, hasher); - } - - for i in 0..100 { - unsafe { - assert_eq!(table.find(i, |x| *x == i).map(|b| b.read()), Some(i)); - } - assert!(table.find(i + 100, |x| *x == i + 100).is_none()); - } - - rehash_in_place(&mut table, hasher); - - for i in 0..100 { - unsafe { - assert_eq!(table.find(i, |x| *x == i).map(|b| b.read()), Some(i)); - } - assert!(table.find(i + 100, |x| *x == i + 100).is_none()); - } - } -} diff --git a/vendor/hashbrown-0.13.2/src/raw/sse2.rs b/vendor/hashbrown-0.13.2/src/raw/sse2.rs deleted file mode 100644 index a0bf6da80..000000000 --- a/vendor/hashbrown-0.13.2/src/raw/sse2.rs +++ /dev/null @@ -1,146 +0,0 @@ -use super::bitmask::BitMask; -use super::EMPTY; -use core::mem; - -#[cfg(target_arch = "x86")] -use core::arch::x86; -#[cfg(target_arch = "x86_64")] -use core::arch::x86_64 as x86; - -pub type BitMaskWord = u16; -pub const BITMASK_STRIDE: usize = 1; -pub const BITMASK_MASK: BitMaskWord = 0xffff; - -/// Abstraction over a group of control bytes which can be scanned in -/// parallel. -/// -/// This implementation uses a 128-bit SSE value. -#[derive(Copy, Clone)] -pub struct Group(x86::__m128i); - -// FIXME: https://github.com/rust-lang/rust-clippy/issues/3859 -#[allow(clippy::use_self)] -impl Group { - /// Number of bytes in the group. - pub const WIDTH: usize = mem::size_of::<Self>(); - - /// Returns a full group of empty bytes, suitable for use as the initial - /// value for an empty hash table. - /// - /// This is guaranteed to be aligned to the group size. - #[inline] - #[allow(clippy::items_after_statements)] - pub const fn static_empty() -> &'static [u8; Group::WIDTH] { - #[repr(C)] - struct AlignedBytes { - _align: [Group; 0], - bytes: [u8; Group::WIDTH], - } - const ALIGNED_BYTES: AlignedBytes = AlignedBytes { - _align: [], - bytes: [EMPTY; Group::WIDTH], - }; - &ALIGNED_BYTES.bytes - } - - /// Loads a group of bytes starting at the given address. - #[inline] - #[allow(clippy::cast_ptr_alignment)] // unaligned load - pub unsafe fn load(ptr: *const u8) -> Self { - Group(x86::_mm_loadu_si128(ptr.cast())) - } - - /// Loads a group of bytes starting at the given address, which must be - /// aligned to `mem::align_of::<Group>()`. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn load_aligned(ptr: *const u8) -> Self { - // FIXME: use align_offset once it stabilizes - debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0); - Group(x86::_mm_load_si128(ptr.cast())) - } - - /// Stores the group of bytes to the given address, which must be - /// aligned to `mem::align_of::<Group>()`. - #[inline] - #[allow(clippy::cast_ptr_alignment)] - pub unsafe fn store_aligned(self, ptr: *mut u8) { - // FIXME: use align_offset once it stabilizes - debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0); - x86::_mm_store_si128(ptr.cast(), self.0); - } - - /// Returns a `BitMask` indicating all bytes in the group which have - /// the given value. - #[inline] - pub fn match_byte(self, byte: u8) -> BitMask { - #[allow( - clippy::cast_possible_wrap, // byte: u8 as i8 - // byte: i32 as u16 - // note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the - // upper 16-bits of the i32 are zeroed: - clippy::cast_sign_loss, - clippy::cast_possible_truncation - )] - unsafe { - let cmp = x86::_mm_cmpeq_epi8(self.0, x86::_mm_set1_epi8(byte as i8)); - BitMask(x86::_mm_movemask_epi8(cmp) as u16) - } - } - - /// Returns a `BitMask` indicating all bytes in the group which are - /// `EMPTY`. - #[inline] - pub fn match_empty(self) -> BitMask { - self.match_byte(EMPTY) - } - - /// Returns a `BitMask` indicating all bytes in the group which are - /// `EMPTY` or `DELETED`. - #[inline] - pub fn match_empty_or_deleted(self) -> BitMask { - #[allow( - // byte: i32 as u16 - // note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the - // upper 16-bits of the i32 are zeroed: - clippy::cast_sign_loss, - clippy::cast_possible_truncation - )] - unsafe { - // A byte is EMPTY or DELETED iff the high bit is set - BitMask(x86::_mm_movemask_epi8(self.0) as u16) - } - } - - /// Returns a `BitMask` indicating all bytes in the group which are full. - #[inline] - pub fn match_full(&self) -> BitMask { - self.match_empty_or_deleted().invert() - } - - /// Performs the following transformation on all bytes in the group: - /// - `EMPTY => EMPTY` - /// - `DELETED => EMPTY` - /// - `FULL => DELETED` - #[inline] - pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self { - // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111 - // and high_bit = 0 (FULL) to 1000_0000 - // - // Here's this logic expanded to concrete values: - // let special = 0 > byte = 1111_1111 (true) or 0000_0000 (false) - // 1111_1111 | 1000_0000 = 1111_1111 - // 0000_0000 | 1000_0000 = 1000_0000 - #[allow( - clippy::cast_possible_wrap, // byte: 0x80_u8 as i8 - )] - unsafe { - let zero = x86::_mm_setzero_si128(); - let special = x86::_mm_cmpgt_epi8(zero, self.0); - Group(x86::_mm_or_si128( - special, - x86::_mm_set1_epi8(0x80_u8 as i8), - )) - } - } -} diff --git a/vendor/hashbrown-0.13.2/src/rustc_entry.rs b/vendor/hashbrown-0.13.2/src/rustc_entry.rs deleted file mode 100644 index 2e8459526..000000000 --- a/vendor/hashbrown-0.13.2/src/rustc_entry.rs +++ /dev/null @@ -1,630 +0,0 @@ -use self::RustcEntry::*; -use crate::map::{make_insert_hash, Drain, HashMap, IntoIter, Iter, IterMut}; -use crate::raw::{Allocator, Bucket, Global, RawTable}; -use core::fmt::{self, Debug}; -use core::hash::{BuildHasher, Hash}; -use core::mem; - -impl<K, V, S, A> HashMap<K, V, S, A> -where - K: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - /// Gets the given key's corresponding entry in the map for in-place manipulation. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut letters = HashMap::new(); - /// - /// for ch in "a short treatise on fungi".chars() { - /// let counter = letters.rustc_entry(ch).or_insert(0); - /// *counter += 1; - /// } - /// - /// assert_eq!(letters[&'s'], 2); - /// assert_eq!(letters[&'t'], 3); - /// assert_eq!(letters[&'u'], 1); - /// assert_eq!(letters.get(&'y'), None); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn rustc_entry(&mut self, key: K) -> RustcEntry<'_, K, V, A> { - let hash = make_insert_hash(&self.hash_builder, &key); - if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) { - RustcEntry::Occupied(RustcOccupiedEntry { - key: Some(key), - elem, - table: &mut self.table, - }) - } else { - // Ideally we would put this in VacantEntry::insert, but Entry is not - // generic over the BuildHasher and adding a generic parameter would be - // a breaking change. - self.reserve(1); - - RustcEntry::Vacant(RustcVacantEntry { - hash, - key, - table: &mut self.table, - }) - } - } -} - -/// A view into a single entry in a map, which may either be vacant or occupied. -/// -/// This `enum` is constructed from the [`rustc_entry`] method on [`HashMap`]. -/// -/// [`HashMap`]: struct.HashMap.html -/// [`rustc_entry`]: struct.HashMap.html#method.rustc_entry -pub enum RustcEntry<'a, K, V, A = Global> -where - A: Allocator + Clone, -{ - /// An occupied entry. - Occupied(RustcOccupiedEntry<'a, K, V, A>), - - /// A vacant entry. - Vacant(RustcVacantEntry<'a, K, V, A>), -} - -impl<K: Debug, V: Debug, A: Allocator + Clone> Debug for RustcEntry<'_, K, V, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), - Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), - } - } -} - -/// A view into an occupied entry in a `HashMap`. -/// It is part of the [`RustcEntry`] enum. -/// -/// [`RustcEntry`]: enum.RustcEntry.html -pub struct RustcOccupiedEntry<'a, K, V, A = Global> -where - A: Allocator + Clone, -{ - key: Option<K>, - elem: Bucket<(K, V)>, - table: &'a mut RawTable<(K, V), A>, -} - -unsafe impl<K, V, A> Send for RustcOccupiedEntry<'_, K, V, A> -where - K: Send, - V: Send, - A: Allocator + Clone + Send, -{ -} -unsafe impl<K, V, A> Sync for RustcOccupiedEntry<'_, K, V, A> -where - K: Sync, - V: Sync, - A: Allocator + Clone + Sync, -{ -} - -impl<K: Debug, V: Debug, A: Allocator + Clone> Debug for RustcOccupiedEntry<'_, K, V, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OccupiedEntry") - .field("key", self.key()) - .field("value", self.get()) - .finish() - } -} - -/// A view into a vacant entry in a `HashMap`. -/// It is part of the [`RustcEntry`] enum. -/// -/// [`RustcEntry`]: enum.RustcEntry.html -pub struct RustcVacantEntry<'a, K, V, A = Global> -where - A: Allocator + Clone, -{ - hash: u64, - key: K, - table: &'a mut RawTable<(K, V), A>, -} - -impl<K: Debug, V, A: Allocator + Clone> Debug for RustcVacantEntry<'_, K, V, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("VacantEntry").field(self.key()).finish() - } -} - -impl<'a, K, V, A: Allocator + Clone> RustcEntry<'a, K, V, A> { - /// Sets the value of the entry, and returns a RustcOccupiedEntry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// let entry = map.rustc_entry("horseyland").insert(37); - /// - /// assert_eq!(entry.key(), &"horseyland"); - /// ``` - pub fn insert(self, value: V) -> RustcOccupiedEntry<'a, K, V, A> { - match self { - Vacant(entry) => entry.insert_entry(value), - Occupied(mut entry) => { - entry.insert(value); - entry - } - } - } - - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.rustc_entry("poneyland").or_insert(3); - /// assert_eq!(map["poneyland"], 3); - /// - /// *map.rustc_entry("poneyland").or_insert(10) *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert(self, default: V) -> &'a mut V - where - K: Hash, - { - match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default), - } - } - - /// Ensures a value is in the entry by inserting the result of the default function if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, String> = HashMap::new(); - /// let s = "hoho".to_string(); - /// - /// map.rustc_entry("poneyland").or_insert_with(|| s); - /// - /// assert_eq!(map["poneyland"], "hoho".to_string()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V - where - K: Hash, - { - match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default()), - } - } - - /// Returns a reference to this entry's key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &K { - match *self { - Occupied(ref entry) => entry.key(), - Vacant(ref entry) => entry.key(), - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.rustc_entry("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 42); - /// - /// map.rustc_entry("poneyland") - /// .and_modify(|e| { *e += 1 }) - /// .or_insert(42); - /// assert_eq!(map["poneyland"], 43); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn and_modify<F>(self, f: F) -> Self - where - F: FnOnce(&mut V), - { - match self { - Occupied(mut entry) => { - f(entry.get_mut()); - Occupied(entry) - } - Vacant(entry) => Vacant(entry), - } - } -} - -impl<'a, K, V: Default, A: Allocator + Clone> RustcEntry<'a, K, V, A> { - /// Ensures a value is in the entry by inserting the default value if empty, - /// and returns a mutable reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// # fn main() { - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, Option<u32>> = HashMap::new(); - /// map.rustc_entry("poneyland").or_default(); - /// - /// assert_eq!(map["poneyland"], None); - /// # } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_default(self) -> &'a mut V - where - K: Hash, - { - match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(Default::default()), - } - } -} - -impl<'a, K, V, A: Allocator + Clone> RustcOccupiedEntry<'a, K, V, A> { - /// Gets a reference to the key in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &K { - unsafe { &self.elem.as_ref().0 } - } - - /// Take the ownership of the key and value from the map. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { - /// // We delete the entry from the map. - /// o.remove_entry(); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove_entry(self) -> (K, V) { - unsafe { self.table.remove(self.elem) } - } - - /// Gets a reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { - /// assert_eq!(o.get(), &12); - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get(&self) -> &V { - unsafe { &self.elem.as_ref().1 } - } - - /// Gets a mutable reference to the value in the entry. - /// - /// If you need a reference to the `RustcOccupiedEntry` which may outlive the - /// destruction of the `RustcEntry` value, see [`into_mut`]. - /// - /// [`into_mut`]: #method.into_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// if let RustcEntry::Occupied(mut o) = map.rustc_entry("poneyland") { - /// *o.get_mut() += 10; - /// assert_eq!(*o.get(), 22); - /// - /// // We can use the same RustcEntry multiple times. - /// *o.get_mut() += 2; - /// } - /// - /// assert_eq!(map["poneyland"], 24); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_mut(&mut self) -> &mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Converts the RustcOccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself. - /// - /// If you need multiple references to the `RustcOccupiedEntry`, see [`get_mut`]. - /// - /// [`get_mut`]: #method.get_mut - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// assert_eq!(map["poneyland"], 12); - /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { - /// *o.into_mut() += 10; - /// } - /// - /// assert_eq!(map["poneyland"], 22); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_mut(self) -> &'a mut V { - unsafe { &mut self.elem.as_mut().1 } - } - - /// Sets the value of the entry, and returns the entry's old value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// if let RustcEntry::Occupied(mut o) = map.rustc_entry("poneyland") { - /// assert_eq!(o.insert(15), 12); - /// } - /// - /// assert_eq!(map["poneyland"], 15); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(&mut self, value: V) -> V { - mem::replace(self.get_mut(), value) - } - - /// Takes the value out of the entry, and returns it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// map.rustc_entry("poneyland").or_insert(12); - /// - /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { - /// assert_eq!(o.remove(), 12); - /// } - /// - /// assert_eq!(map.contains_key("poneyland"), false); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove(self) -> V { - self.remove_entry().1 - } - - /// Replaces the entry, returning the old key and value. The new key in the hash map will be - /// the key used to create this entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{RustcEntry, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap<Rc<String>, u32> = HashMap::new(); - /// map.insert(Rc::new("Stringthing".to_string()), 15); - /// - /// let my_key = Rc::new("Stringthing".to_string()); - /// - /// if let RustcEntry::Occupied(entry) = map.rustc_entry(my_key) { - /// // Also replace the key with a handle to our other key. - /// let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16); - /// } - /// - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_entry(self, value: V) -> (K, V) { - let entry = unsafe { self.elem.as_mut() }; - - let old_key = mem::replace(&mut entry.0, self.key.unwrap()); - let old_value = mem::replace(&mut entry.1, value); - - (old_key, old_value) - } - - /// Replaces the key in the hash map with the key used to create this entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_map::{RustcEntry, HashMap}; - /// use std::rc::Rc; - /// - /// let mut map: HashMap<Rc<String>, u32> = HashMap::new(); - /// let mut known_strings: Vec<Rc<String>> = Vec::new(); - /// - /// // Initialise known strings, run program, etc. - /// - /// reclaim_memory(&mut map, &known_strings); - /// - /// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) { - /// for s in known_strings { - /// if let RustcEntry::Occupied(entry) = map.rustc_entry(s.clone()) { - /// // Replaces the entry's key with our version of it in `known_strings`. - /// entry.replace_key(); - /// } - /// } - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace_key(self) -> K { - let entry = unsafe { self.elem.as_mut() }; - mem::replace(&mut entry.0, self.key.unwrap()) - } -} - -impl<'a, K, V, A: Allocator + Clone> RustcVacantEntry<'a, K, V, A> { - /// Gets a reference to the key that would be used when inserting a value - /// through the `RustcVacantEntry`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &K { - &self.key - } - - /// Take ownership of the key. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") { - /// v.into_key(); - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_key(self) -> K { - self.key - } - - /// Sets the value of the entry with the RustcVacantEntry's key, - /// and returns a mutable reference to it. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// if let RustcEntry::Vacant(o) = map.rustc_entry("poneyland") { - /// o.insert(37); - /// } - /// assert_eq!(map["poneyland"], 37); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, value: V) -> &'a mut V { - unsafe { - let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); - &mut bucket.as_mut().1 - } - } - - /// Sets the value of the entry with the RustcVacantEntry's key, - /// and returns a RustcOccupiedEntry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashMap; - /// use hashbrown::hash_map::RustcEntry; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") { - /// let o = v.insert_entry(37); - /// assert_eq!(o.get(), &37); - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert_entry(self, value: V) -> RustcOccupiedEntry<'a, K, V, A> { - let bucket = unsafe { self.table.insert_no_grow(self.hash, (self.key, value)) }; - RustcOccupiedEntry { - key: None, - elem: bucket, - table: self.table, - } - } -} - -impl<K, V> IterMut<'_, K, V> { - /// Returns a iterator of references over the remaining items. - #[cfg_attr(feature = "inline-more", inline)] - pub fn rustc_iter(&self) -> Iter<'_, K, V> { - self.iter() - } -} - -impl<K, V> IntoIter<K, V> { - /// Returns a iterator of references over the remaining items. - #[cfg_attr(feature = "inline-more", inline)] - pub fn rustc_iter(&self) -> Iter<'_, K, V> { - self.iter() - } -} - -impl<K, V> Drain<'_, K, V> { - /// Returns a iterator of references over the remaining items. - #[cfg_attr(feature = "inline-more", inline)] - pub fn rustc_iter(&self) -> Iter<'_, K, V> { - self.iter() - } -} diff --git a/vendor/hashbrown-0.13.2/src/scopeguard.rs b/vendor/hashbrown-0.13.2/src/scopeguard.rs deleted file mode 100644 index 382d06043..000000000 --- a/vendor/hashbrown-0.13.2/src/scopeguard.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Extracted from the scopeguard crate -use core::{ - mem::ManuallyDrop, - ops::{Deref, DerefMut}, - ptr, -}; - -pub struct ScopeGuard<T, F> -where - F: FnMut(&mut T), -{ - dropfn: F, - value: T, -} - -#[inline] -pub fn guard<T, F>(value: T, dropfn: F) -> ScopeGuard<T, F> -where - F: FnMut(&mut T), -{ - ScopeGuard { dropfn, value } -} - -impl<T, F> ScopeGuard<T, F> -where - F: FnMut(&mut T), -{ - #[inline] - pub fn into_inner(guard: Self) -> T { - // Cannot move out of Drop-implementing types, so - // ptr::read the value out of a ManuallyDrop<Self> - // Don't use mem::forget as that might invalidate value - let guard = ManuallyDrop::new(guard); - unsafe { - let value = ptr::read(&guard.value); - // read the closure so that it is dropped - let _ = ptr::read(&guard.dropfn); - value - } - } -} - -impl<T, F> Deref for ScopeGuard<T, F> -where - F: FnMut(&mut T), -{ - type Target = T; - #[inline] - fn deref(&self) -> &T { - &self.value - } -} - -impl<T, F> DerefMut for ScopeGuard<T, F> -where - F: FnMut(&mut T), -{ - #[inline] - fn deref_mut(&mut self) -> &mut T { - &mut self.value - } -} - -impl<T, F> Drop for ScopeGuard<T, F> -where - F: FnMut(&mut T), -{ - #[inline] - fn drop(&mut self) { - (self.dropfn)(&mut self.value); - } -} diff --git a/vendor/hashbrown-0.13.2/src/set.rs b/vendor/hashbrown-0.13.2/src/set.rs deleted file mode 100644 index a8f24de80..000000000 --- a/vendor/hashbrown-0.13.2/src/set.rs +++ /dev/null @@ -1,2889 +0,0 @@ -#[cfg(feature = "raw")] -use crate::raw::RawTable; -use crate::{Equivalent, TryReserveError}; -use alloc::borrow::ToOwned; -use core::fmt; -use core::hash::{BuildHasher, Hash}; -use core::iter::{Chain, FromIterator, FusedIterator}; -use core::mem; -use core::ops::{BitAnd, BitOr, BitXor, Sub}; - -use super::map::{self, ConsumeAllOnDrop, DefaultHashBuilder, DrainFilterInner, HashMap, Keys}; -use crate::raw::{Allocator, Global}; - -// Future Optimization (FIXME!) -// ============================= -// -// Iteration over zero sized values is a noop. There is no need -// for `bucket.val` in the case of HashSet. I suppose we would need HKT -// to get rid of it properly. - -/// A hash set implemented as a `HashMap` where the value is `()`. -/// -/// As with the [`HashMap`] type, a `HashSet` requires that the elements -/// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by -/// using `#[derive(PartialEq, Eq, Hash)]`. If you implement these yourself, -/// it is important that the following property holds: -/// -/// ```text -/// k1 == k2 -> hash(k1) == hash(k2) -/// ``` -/// -/// In other words, if two keys are equal, their hashes must be equal. -/// -/// -/// It is a logic error for an item to be modified in such a way that the -/// item's hash, as determined by the [`Hash`] trait, or its equality, as -/// determined by the [`Eq`] trait, changes while it is in the set. This is -/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or -/// unsafe code. -/// -/// It is also a logic error for the [`Hash`] implementation of a key to panic. -/// This is generally only possible if the trait is implemented manually. If a -/// panic does occur then the contents of the `HashSet` may become corrupted and -/// some items may be dropped from the table. -/// -/// # Examples -/// -/// ``` -/// use hashbrown::HashSet; -/// // Type inference lets us omit an explicit type signature (which -/// // would be `HashSet<String>` in this example). -/// let mut books = HashSet::new(); -/// -/// // Add some books. -/// books.insert("A Dance With Dragons".to_string()); -/// books.insert("To Kill a Mockingbird".to_string()); -/// books.insert("The Odyssey".to_string()); -/// books.insert("The Great Gatsby".to_string()); -/// -/// // 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); -/// } -/// ``` -/// -/// The easiest way to use `HashSet` with a custom type is to derive -/// [`Eq`] and [`Hash`]. We must also derive [`PartialEq`]. This will in the -/// future be implied by [`Eq`]. -/// -/// ``` -/// use hashbrown::HashSet; -/// #[derive(Hash, Eq, PartialEq, Debug)] -/// struct Viking { -/// name: String, -/// power: usize, -/// } -/// -/// let mut vikings = HashSet::new(); -/// -/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 }); -/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 }); -/// vikings.insert(Viking { name: "Olaf".to_string(), power: 4 }); -/// vikings.insert(Viking { name: "Harald".to_string(), power: 8 }); -/// -/// // Use derived implementation to print the vikings. -/// for x in &vikings { -/// println!("{:?}", x); -/// } -/// ``` -/// -/// A `HashSet` with fixed list of elements can be initialized from an array: -/// -/// ``` -/// use hashbrown::HashSet; -/// -/// let viking_names: HashSet<&'static str> = -/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect(); -/// // use the values stored in the set -/// ``` -/// -/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html -/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html -/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html -/// [`HashMap`]: struct.HashMap.html -/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html -/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html -pub struct HashSet<T, S = DefaultHashBuilder, A: Allocator + Clone = Global> { - pub(crate) map: HashMap<T, (), S, A>, -} - -impl<T: Clone, S: Clone, A: Allocator + Clone> Clone for HashSet<T, S, A> { - fn clone(&self) -> Self { - HashSet { - map: self.map.clone(), - } - } - - fn clone_from(&mut self, source: &Self) { - self.map.clone_from(&source.map); - } -} - -#[cfg(feature = "ahash")] -impl<T> HashSet<T, DefaultHashBuilder> { - /// Creates an empty `HashSet`. - /// - /// The hash set is initially created with a capacity of 0, so it will not allocate until it - /// is first inserted into. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashSet`], for example with - /// [`with_hasher`](HashSet::with_hasher) method. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let set: HashSet<i32> = HashSet::new(); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn new() -> Self { - Self { - map: HashMap::new(), - } - } - - /// Creates an empty `HashSet` with the specified capacity. - /// - /// The hash set will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash set will not allocate. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashSet`], for example with - /// [`with_capacity_and_hasher`](HashSet::with_capacity_and_hasher) method. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let set: HashSet<i32> = HashSet::with_capacity(10); - /// assert!(set.capacity() >= 10); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn with_capacity(capacity: usize) -> Self { - Self { - map: HashMap::with_capacity(capacity), - } - } -} - -#[cfg(feature = "ahash")] -impl<T: Hash + Eq, A: Allocator + Clone> HashSet<T, DefaultHashBuilder, A> { - /// Creates an empty `HashSet`. - /// - /// The hash set is initially created with a capacity of 0, so it will not allocate until it - /// is first inserted into. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashSet`], for example with - /// [`with_hasher_in`](HashSet::with_hasher_in) method. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let set: HashSet<i32> = HashSet::new(); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn new_in(alloc: A) -> Self { - Self { - map: HashMap::new_in(alloc), - } - } - - /// Creates an empty `HashSet` with the specified capacity. - /// - /// The hash set will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash set will not allocate. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashSet`], for example with - /// [`with_capacity_and_hasher_in`](HashSet::with_capacity_and_hasher_in) method. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let set: HashSet<i32> = HashSet::with_capacity(10); - /// assert!(set.capacity() >= 10); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - Self { - map: HashMap::with_capacity_in(capacity, alloc), - } - } -} - -impl<T, S, A: Allocator + Clone> HashSet<T, S, A> { - /// Returns the number of elements the set can hold without reallocating. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let set: HashSet<i32> = HashSet::with_capacity(100); - /// assert!(set.capacity() >= 100); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn capacity(&self) -> usize { - self.map.capacity() - } - - /// An iterator visiting all elements in arbitrary order. - /// The iterator element type is `&'a T`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a"); - /// set.insert("b"); - /// - /// // Will print in an arbitrary order. - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn iter(&self) -> Iter<'_, T> { - Iter { - iter: self.map.keys(), - } - } - - /// Returns the number of elements in the set. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1); - /// assert_eq!(v.len(), 1); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn len(&self) -> usize { - self.map.len() - } - - /// Returns `true` if the set contains no elements. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1); - /// assert!(!v.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn is_empty(&self) -> bool { - self.map.is_empty() - } - - /// Clears the set, returning all elements in an iterator. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert!(!set.is_empty()); - /// - /// // print 1, 2, 3 in an arbitrary order - /// for i in set.drain() { - /// println!("{}", i); - /// } - /// - /// assert!(set.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn drain(&mut self) -> Drain<'_, T, A> { - Drain { - iter: self.map.drain(), - } - } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` such that `f(&e)` returns `false`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let xs = [1,2,3,4,5,6]; - /// let mut set: HashSet<i32> = xs.iter().cloned().collect(); - /// set.retain(|&k| k % 2 == 0); - /// assert_eq!(set.len(), 3); - /// ``` - pub fn retain<F>(&mut self, mut f: F) - where - F: FnMut(&T) -> bool, - { - self.map.retain(|k, _| f(k)); - } - - /// Drains elements which are true under the given predicate, - /// and returns an iterator over the removed items. - /// - /// In other words, move all elements `e` such that `f(&e)` returns `true` out - /// into another iterator. - /// - /// When the returned DrainedFilter is dropped, any remaining elements that satisfy - /// the predicate are dropped from the set. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<i32> = (0..8).collect(); - /// let drained: HashSet<i32> = set.drain_filter(|v| v % 2 == 0).collect(); - /// - /// let mut evens = drained.into_iter().collect::<Vec<_>>(); - /// let mut odds = set.into_iter().collect::<Vec<_>>(); - /// evens.sort(); - /// odds.sort(); - /// - /// assert_eq!(evens, vec![0, 2, 4, 6]); - /// assert_eq!(odds, vec![1, 3, 5, 7]); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, T, F, A> - where - F: FnMut(&T) -> bool, - { - DrainFilter { - f, - inner: DrainFilterInner { - iter: unsafe { self.map.table.iter() }, - table: &mut self.map.table, - }, - } - } - - /// Clears the set, removing all values. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut v = HashSet::new(); - /// v.insert(1); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn clear(&mut self) { - self.map.clear(); - } -} - -impl<T, S> HashSet<T, S, Global> { - /// Creates a new empty hash set which will use the given hasher to hash - /// keys. - /// - /// The hash set is initially created with a capacity of 0, so it will not - /// allocate until it is first inserted into. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashSet`]. - /// - /// The `hash_builder` passed should implement the [`BuildHasher`] trait for - /// the HashSet to be useful, see its documentation for details. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut set = HashSet::with_hasher(s); - /// set.insert(2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub const fn with_hasher(hasher: S) -> Self { - Self { - map: HashMap::with_hasher(hasher), - } - } - - /// Creates an empty `HashSet` with the specified capacity, using - /// `hasher` to hash the keys. - /// - /// The hash set will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash set will not allocate. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashSet`]. - /// - /// The `hash_builder` passed should implement the [`BuildHasher`] trait for - /// the HashSet to be useful, see its documentation for details. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut set = HashSet::with_capacity_and_hasher(10, s); - /// set.insert(1); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self { - Self { - map: HashMap::with_capacity_and_hasher(capacity, hasher), - } - } -} - -impl<T, S, A> HashSet<T, S, A> -where - A: Allocator + Clone, -{ - /// Returns a reference to the underlying allocator. - #[inline] - pub fn allocator(&self) -> &A { - self.map.allocator() - } - - /// Creates a new empty hash set which will use the given hasher to hash - /// keys. - /// - /// The hash set is initially created with a capacity of 0, so it will not - /// allocate until it is first inserted into. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashSet`]. - /// - /// The `hash_builder` passed should implement the [`BuildHasher`] trait for - /// the HashSet to be useful, see its documentation for details. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut set = HashSet::with_hasher(s); - /// set.insert(2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub const fn with_hasher_in(hasher: S, alloc: A) -> Self { - Self { - map: HashMap::with_hasher_in(hasher, alloc), - } - } - - /// Creates an empty `HashSet` with the specified capacity, using - /// `hasher` to hash the keys. - /// - /// The hash set will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash set will not allocate. - /// - /// # HashDoS resistance - /// - /// The `hash_builder` normally use a fixed key by default and that does - /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`]. - /// Users who require HashDoS resistance should explicitly use - /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] - /// as the hasher when creating a [`HashSet`]. - /// - /// The `hash_builder` passed should implement the [`BuildHasher`] trait for - /// the HashSet to be useful, see its documentation for details. - /// - /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack - /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let s = DefaultHashBuilder::default(); - /// let mut set = HashSet::with_capacity_and_hasher(10, s); - /// set.insert(1); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn with_capacity_and_hasher_in(capacity: usize, hasher: S, alloc: A) -> Self { - Self { - map: HashMap::with_capacity_and_hasher_in(capacity, hasher, alloc), - } - } - - /// Returns a reference to the set's [`BuildHasher`]. - /// - /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_map::DefaultHashBuilder; - /// - /// let hasher = DefaultHashBuilder::default(); - /// let set: HashSet<i32> = HashSet::with_hasher(hasher); - /// let hasher: &DefaultHashBuilder = set.hasher(); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn hasher(&self) -> &S { - self.map.hasher() - } -} - -impl<T, S, A> HashSet<T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `HashSet`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Panics - /// - /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`] the program - /// in case of allocation error. Use [`try_reserve`](HashSet::try_reserve) instead - /// if you want to handle memory allocation failure. - /// - /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html - /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let mut set: HashSet<i32> = HashSet::new(); - /// set.reserve(10); - /// assert!(set.capacity() >= 10); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn reserve(&mut self, additional: usize) { - self.map.reserve(additional); - } - - /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `HashSet<K,V>`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let mut set: HashSet<i32> = HashSet::new(); - /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.map.try_reserve(additional) - } - - /// Shrinks the capacity of the set as much as possible. It will drop - /// down as much as possible while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set = HashSet::with_capacity(100); - /// set.insert(1); - /// set.insert(2); - /// assert!(set.capacity() >= 100); - /// set.shrink_to_fit(); - /// assert!(set.capacity() >= 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn shrink_to_fit(&mut self) { - self.map.shrink_to_fit(); - } - - /// Shrinks the capacity of the set with a lower limit. It will drop - /// down no lower than the supplied limit while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// Panics if the current capacity is smaller than the supplied - /// minimum capacity. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set = HashSet::with_capacity(100); - /// set.insert(1); - /// set.insert(2); - /// assert!(set.capacity() >= 100); - /// set.shrink_to(10); - /// assert!(set.capacity() >= 10); - /// set.shrink_to(0); - /// assert!(set.capacity() >= 2); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.map.shrink_to(min_capacity); - } - - /// Visits the values representing the difference, - /// i.e., the values that are in `self` but not in `other`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [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: HashSet<_> = a.difference(&b).collect(); - /// assert_eq!(diff, [1].iter().collect()); - /// - /// // Note that difference is not symmetric, - /// // and `b - a` means something else: - /// let diff: HashSet<_> = b.difference(&a).collect(); - /// assert_eq!(diff, [4].iter().collect()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, S, A> { - 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 hashbrown::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); - /// - /// // Print 1, 4 in arbitrary order. - /// for x in a.symmetric_difference(&b) { - /// println!("{}", x); - /// } - /// - /// let diff1: HashSet<_> = a.symmetric_difference(&b).collect(); - /// let diff2: HashSet<_> = b.symmetric_difference(&a).collect(); - /// - /// assert_eq!(diff1, diff2); - /// assert_eq!(diff1, [1, 4].iter().collect()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, S, A> { - SymmetricDifference { - iter: 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 hashbrown::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); - /// - /// // Print 2, 3 in arbitrary order. - /// for x in a.intersection(&b) { - /// println!("{}", x); - /// } - /// - /// let intersection: HashSet<_> = a.intersection(&b).collect(); - /// assert_eq!(intersection, [2, 3].iter().collect()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, S, A> { - let (smaller, larger) = if self.len() <= other.len() { - (self, other) - } else { - (other, self) - }; - Intersection { - iter: smaller.iter(), - other: larger, - } - } - - /// Visits the values representing the union, - /// i.e., all the values in `self` or `other`, without duplicates. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); - /// - /// // Print 1, 2, 3, 4 in arbitrary order. - /// for x in a.union(&b) { - /// println!("{}", x); - /// } - /// - /// let union: HashSet<_> = a.union(&b).collect(); - /// assert_eq!(union, [1, 2, 3, 4].iter().collect()); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T, S, A> { - // We'll iterate one set in full, and only the remaining difference from the other. - // Use the smaller set for the difference in order to reduce hash lookups. - let (smaller, larger) = if self.len() <= other.len() { - (self, other) - } else { - (other, self) - }; - Union { - iter: larger.iter().chain(smaller.difference(larger)), - } - } - - /// 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 hashbrown::HashSet; - /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert_eq!(set.contains(&1), true); - /// assert_eq!(set.contains(&4), false); - /// ``` - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - #[cfg_attr(feature = "inline-more", inline)] - pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool - where - Q: Hash + Equivalent<T>, - { - self.map.contains_key(value) - } - - /// Returns a reference to the value in the set, if any, that is equal to the given 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 hashbrown::HashSet; - /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert_eq!(set.get(&2), Some(&2)); - /// assert_eq!(set.get(&4), None); - /// ``` - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - #[cfg_attr(feature = "inline-more", inline)] - pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T> - where - Q: Hash + Equivalent<T>, - { - // Avoid `Option::map` because it bloats LLVM IR. - match self.map.get_key_value(value) { - Some((k, _)) => Some(k), - None => None, - } - } - - /// Inserts the given `value` into the set if it is not present, then - /// returns a reference to the value in the set. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert_eq!(set.len(), 3); - /// assert_eq!(set.get_or_insert(2), &2); - /// assert_eq!(set.get_or_insert(100), &100); - /// assert_eq!(set.len(), 4); // 100 was inserted - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_or_insert(&mut self, value: T) -> &T { - // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with - // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`. - self.map - .raw_entry_mut() - .from_key(&value) - .or_insert(value, ()) - .0 - } - - /// Inserts an owned copy of the given `value` into the set if it is not - /// present, then returns a reference to the value in the set. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<String> = ["cat", "dog", "horse"] - /// .iter().map(|&pet| pet.to_owned()).collect(); - /// - /// assert_eq!(set.len(), 3); - /// for &pet in &["cat", "dog", "fish"] { - /// let value = set.get_or_insert_owned(pet); - /// assert_eq!(value, pet); - /// } - /// assert_eq!(set.len(), 4); // a new "fish" was inserted - /// ``` - #[inline] - pub fn get_or_insert_owned<Q: ?Sized>(&mut self, value: &Q) -> &T - where - Q: Hash + Equivalent<T> + ToOwned<Owned = T>, - { - // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with - // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`. - self.map - .raw_entry_mut() - .from_key(value) - .or_insert_with(|| (value.to_owned(), ())) - .0 - } - - /// Inserts a value computed from `f` into the set if the given `value` is - /// not present, then returns a reference to the value in the set. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<String> = ["cat", "dog", "horse"] - /// .iter().map(|&pet| pet.to_owned()).collect(); - /// - /// assert_eq!(set.len(), 3); - /// for &pet in &["cat", "dog", "fish"] { - /// let value = set.get_or_insert_with(pet, str::to_owned); - /// assert_eq!(value, pet); - /// } - /// assert_eq!(set.len(), 4); // a new "fish" was inserted - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get_or_insert_with<Q: ?Sized, F>(&mut self, value: &Q, f: F) -> &T - where - Q: Hash + Equivalent<T>, - F: FnOnce(&Q) -> T, - { - // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with - // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`. - self.map - .raw_entry_mut() - .from_key(value) - .or_insert_with(|| (f(value), ())) - .0 - } - - /// Gets the given value's corresponding entry in the set for in-place manipulation. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_set::Entry::*; - /// - /// let mut singles = HashSet::new(); - /// let mut dupes = HashSet::new(); - /// - /// for ch in "a short treatise on fungi".chars() { - /// if let Vacant(dupe_entry) = dupes.entry(ch) { - /// // We haven't already seen a duplicate, so - /// // check if we've at least seen it once. - /// match singles.entry(ch) { - /// Vacant(single_entry) => { - /// // We found a new character for the first time. - /// single_entry.insert() - /// } - /// Occupied(single_entry) => { - /// // We've already seen this once, "move" it to dupes. - /// single_entry.remove(); - /// dupe_entry.insert(); - /// } - /// } - /// } - /// } - /// - /// assert!(!singles.contains(&'t') && dupes.contains(&'t')); - /// assert!(singles.contains(&'u') && !dupes.contains(&'u')); - /// assert!(!singles.contains(&'v') && !dupes.contains(&'v')); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn entry(&mut self, value: T) -> Entry<'_, T, S, A> { - match self.map.entry(value) { - map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { inner: entry }), - map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { inner: entry }), - } - } - - /// Returns `true` if `self` has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let mut b = HashSet::new(); - /// - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(4); - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(1); - /// assert_eq!(a.is_disjoint(&b), false); - /// ``` - pub fn is_disjoint(&self, other: &Self) -> bool { - 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 hashbrown::HashSet; - /// - /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(2); - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(4); - /// assert_eq!(set.is_subset(&sup), false); - /// ``` - pub fn is_subset(&self, other: &Self) -> bool { - self.len() <= other.len() && 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 hashbrown::HashSet; - /// - /// let sub: HashSet<_> = [1, 2].iter().cloned().collect(); - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(0); - /// set.insert(1); - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(2); - /// assert_eq!(set.is_superset(&sub), true); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn is_superset(&self, other: &Self) -> bool { - 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 hashbrown::HashSet; - /// - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.insert(2), true); - /// assert_eq!(set.insert(2), false); - /// assert_eq!(set.len(), 1); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(&mut self, value: T) -> bool { - self.map.insert(value, ()).is_none() - } - - /// Insert a value the set without checking if the value already exists in the set. - /// - /// Returns a reference to the value just inserted. - /// - /// This operation is safe if a value does not exist in the set. - /// - /// However, if a value exists in the set already, the behavior is unspecified: - /// this operation may panic, loop forever, or any following operation with the set - /// may panic, loop forever or return arbitrary result. - /// - /// That said, this operation (and following operations) are guaranteed to - /// not violate memory safety. - /// - /// This operation is faster than regular insert, because it does not perform - /// lookup before insertion. - /// - /// This operation is useful during initial population of the set. - /// For example, when constructing a set from another set, we know - /// that values are unique. - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert_unique_unchecked(&mut self, value: T) -> &T { - self.map.insert_unique_unchecked(value, ()).0 - } - - /// Adds a value to the set, replacing the existing value, if any, that is equal to the given - /// one. Returns the replaced value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set = HashSet::new(); - /// set.insert(Vec::<i32>::new()); - /// - /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0); - /// set.replace(Vec::with_capacity(10)); - /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace(&mut self, value: T) -> Option<T> { - match self.map.entry(value) { - map::Entry::Occupied(occupied) => Some(occupied.replace_key()), - map::Entry::Vacant(vacant) => { - vacant.insert(()); - None - } - } - } - - /// Removes a value from the set. Returns whether 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 hashbrown::HashSet; - /// - /// let mut set = HashSet::new(); - /// - /// set.insert(2); - /// assert_eq!(set.remove(&2), true); - /// assert_eq!(set.remove(&2), false); - /// ``` - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool - where - Q: Hash + Equivalent<T>, - { - self.map.remove(value).is_some() - } - - /// Removes and returns the value in the set, if any, that is equal to the given one. - /// - /// 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 hashbrown::HashSet; - /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert_eq!(set.take(&2), Some(2)); - /// assert_eq!(set.take(&2), None); - /// ``` - /// - /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html - /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html - #[cfg_attr(feature = "inline-more", inline)] - pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T> - where - Q: Hash + Equivalent<T>, - { - // Avoid `Option::map` because it bloats LLVM IR. - match self.map.remove_entry(value) { - Some((k, _)) => Some(k), - None => None, - } - } - - /// Returns a mutable reference to the [`RawTable`] used underneath [`HashSet`]. - /// This function is only available if the `raw` feature of the crate is enabled. - /// - /// # Note - /// - /// Calling this function is safe, but using the raw hash table API may require - /// unsafe functions or blocks. - /// - /// `RawTable` API gives the lowest level of control under the set that can be useful - /// for extending the HashSet's API, but may lead to *[undefined behavior]*. - /// - /// [`HashSet`]: struct.HashSet.html - /// [`RawTable`]: crate::raw::RawTable - /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html - #[cfg(feature = "raw")] - #[cfg_attr(feature = "inline-more", inline)] - pub fn raw_table(&mut self) -> &mut RawTable<(T, ()), A> { - self.map.raw_table() - } -} - -impl<T, S, A> PartialEq for HashSet<T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - fn eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - - self.iter().all(|key| other.contains(key)) - } -} - -impl<T, S, A> Eq for HashSet<T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ -} - -impl<T, S, A> fmt::Debug for HashSet<T, S, A> -where - T: fmt::Debug, - A: Allocator + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_set().entries(self.iter()).finish() - } -} - -impl<T, S, A> From<HashMap<T, (), S, A>> for HashSet<T, S, A> -where - A: Allocator + Clone, -{ - fn from(map: HashMap<T, (), S, A>) -> Self { - Self { map } - } -} - -impl<T, S, A> FromIterator<T> for HashSet<T, S, A> -where - T: Eq + Hash, - S: BuildHasher + Default, - A: Default + Allocator + Clone, -{ - #[cfg_attr(feature = "inline-more", inline)] - fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { - let mut set = Self::with_hasher_in(Default::default(), Default::default()); - set.extend(iter); - set - } -} - -// The default hasher is used to match the std implementation signature -#[cfg(feature = "ahash")] -impl<T, A, const N: usize> From<[T; N]> for HashSet<T, DefaultHashBuilder, A> -where - T: Eq + Hash, - A: Default + Allocator + Clone, -{ - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let set1 = HashSet::from([1, 2, 3, 4]); - /// let set2: HashSet<_> = [1, 2, 3, 4].into(); - /// assert_eq!(set1, set2); - /// ``` - fn from(arr: [T; N]) -> Self { - arr.into_iter().collect() - } -} - -impl<T, S, A> Extend<T> for HashSet<T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - #[cfg_attr(feature = "inline-more", inline)] - fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { - self.map.extend(iter.into_iter().map(|k| (k, ()))); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_one(&mut self, k: T) { - self.map.insert(k, ()); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_reserve(&mut self, additional: usize) { - Extend::<(T, ())>::extend_reserve(&mut self.map, additional); - } -} - -impl<'a, T, S, A> Extend<&'a T> for HashSet<T, S, A> -where - T: 'a + Eq + Hash + Copy, - S: BuildHasher, - A: Allocator + Clone, -{ - #[cfg_attr(feature = "inline-more", inline)] - fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { - self.extend(iter.into_iter().copied()); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_one(&mut self, k: &'a T) { - self.map.insert(*k, ()); - } - - #[inline] - #[cfg(feature = "nightly")] - fn extend_reserve(&mut self, additional: usize) { - Extend::<(T, ())>::extend_reserve(&mut self.map, additional); - } -} - -impl<T, S, A> Default for HashSet<T, S, A> -where - S: Default, - A: Default + Allocator + Clone, -{ - /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher. - #[cfg_attr(feature = "inline-more", inline)] - fn default() -> Self { - Self { - map: HashMap::default(), - } - } -} - -impl<T, S, A> BitOr<&HashSet<T, S, A>> for &HashSet<T, S, A> -where - T: Eq + Hash + Clone, - S: BuildHasher + Default, - A: Allocator + Clone, -{ - type Output = HashSet<T, S>; - - /// Returns the union of `self` and `rhs` as a new `HashSet<T, S>`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a | &b; - /// - /// let mut i = 0; - /// let expected = [1, 2, 3, 4, 5]; - /// for x in &set { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitor(self, rhs: &HashSet<T, S, A>) -> HashSet<T, S> { - self.union(rhs).cloned().collect() - } -} - -impl<T, S, A> BitAnd<&HashSet<T, S, A>> for &HashSet<T, S, A> -where - T: Eq + Hash + Clone, - S: BuildHasher + Default, - A: Allocator + Clone, -{ - type Output = HashSet<T, S>; - - /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, S>`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect(); - /// - /// let set = &a & &b; - /// - /// let mut i = 0; - /// let expected = [2, 3]; - /// for x in &set { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitand(self, rhs: &HashSet<T, S, A>) -> HashSet<T, S> { - self.intersection(rhs).cloned().collect() - } -} - -impl<T, S> BitXor<&HashSet<T, S>> for &HashSet<T, S> -where - T: Eq + Hash + Clone, - S: BuildHasher + Default, -{ - type Output = HashSet<T, S>; - - /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, S>`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a ^ &b; - /// - /// let mut i = 0; - /// let expected = [1, 2, 4, 5]; - /// for x in &set { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitxor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> { - self.symmetric_difference(rhs).cloned().collect() - } -} - -impl<T, S> Sub<&HashSet<T, S>> for &HashSet<T, S> -where - T: Eq + Hash + Clone, - S: BuildHasher + Default, -{ - type Output = HashSet<T, S>; - - /// Returns the difference of `self` and `rhs` as a new `HashSet<T, S>`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a - &b; - /// - /// let mut i = 0; - /// let expected = [1, 2]; - /// for x in &set { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn sub(self, rhs: &HashSet<T, S>) -> HashSet<T, S> { - self.difference(rhs).cloned().collect() - } -} - -/// An iterator over the items of a `HashSet`. -/// -/// This `struct` is created by the [`iter`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`iter`]: struct.HashSet.html#method.iter -pub struct Iter<'a, K> { - iter: Keys<'a, K, ()>, -} - -/// An owning iterator over the items of a `HashSet`. -/// -/// This `struct` is created by the [`into_iter`] method on [`HashSet`] -/// (provided by the `IntoIterator` trait). See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`into_iter`]: struct.HashSet.html#method.into_iter -pub struct IntoIter<K, A: Allocator + Clone = Global> { - iter: map::IntoIter<K, (), A>, -} - -/// A draining iterator over the items of a `HashSet`. -/// -/// This `struct` is created by the [`drain`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`drain`]: struct.HashSet.html#method.drain -pub struct Drain<'a, K, A: Allocator + Clone = Global> { - iter: map::Drain<'a, K, (), A>, -} - -/// A draining iterator over entries of a `HashSet` which don't satisfy the predicate `f`. -/// -/// This `struct` is created by the [`drain_filter`] method on [`HashSet`]. See its -/// documentation for more. -/// -/// [`drain_filter`]: struct.HashSet.html#method.drain_filter -/// [`HashSet`]: struct.HashSet.html -pub struct DrainFilter<'a, K, F, A: Allocator + Clone = Global> -where - F: FnMut(&K) -> bool, -{ - f: F, - inner: DrainFilterInner<'a, K, (), A>, -} - -/// A lazy iterator producing elements in the intersection of `HashSet`s. -/// -/// This `struct` is created by the [`intersection`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`intersection`]: struct.HashSet.html#method.intersection -pub struct Intersection<'a, T, S, A: Allocator + Clone = Global> { - // iterator of the first set - iter: Iter<'a, T>, - // the second set - other: &'a HashSet<T, S, A>, -} - -/// A lazy iterator producing elements in the difference of `HashSet`s. -/// -/// This `struct` is created by the [`difference`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`difference`]: struct.HashSet.html#method.difference -pub struct Difference<'a, T, S, A: Allocator + Clone = Global> { - // iterator of the first set - iter: Iter<'a, T>, - // the second set - other: &'a HashSet<T, S, A>, -} - -/// A lazy iterator producing elements in the symmetric difference of `HashSet`s. -/// -/// This `struct` is created by the [`symmetric_difference`] method on -/// [`HashSet`]. See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference -pub struct SymmetricDifference<'a, T, S, A: Allocator + Clone = Global> { - iter: Chain<Difference<'a, T, S, A>, Difference<'a, T, S, A>>, -} - -/// A lazy iterator producing elements in the union of `HashSet`s. -/// -/// This `struct` is created by the [`union`] method on [`HashSet`]. -/// See its documentation for more. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`union`]: struct.HashSet.html#method.union -pub struct Union<'a, T, S, A: Allocator + Clone = Global> { - iter: Chain<Iter<'a, T>, Difference<'a, T, S, A>>, -} - -impl<'a, T, S, A: Allocator + Clone> IntoIterator for &'a HashSet<T, S, A> { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - - #[cfg_attr(feature = "inline-more", inline)] - fn into_iter(self) -> Iter<'a, T> { - self.iter() - } -} - -impl<T, S, A: Allocator + Clone> IntoIterator for HashSet<T, S, A> { - type Item = T; - type IntoIter = IntoIter<T, A>; - - /// Creates a consuming iterator, that is, one that moves each value out - /// of the set in arbitrary order. The set cannot be used after calling - /// this. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a".to_string()); - /// set.insert("b".to_string()); - /// - /// // Not possible to collect to a Vec<String> with a regular `.iter()`. - /// let v: Vec<String> = set.into_iter().collect(); - /// - /// // Will print in an arbitrary order. - /// for x in &v { - /// println!("{}", x); - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - fn into_iter(self) -> IntoIter<T, A> { - IntoIter { - iter: self.map.into_iter(), - } - } -} - -impl<K> Clone for Iter<'_, K> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Iter { - iter: self.iter.clone(), - } - } -} -impl<'a, K> Iterator for Iter<'a, K> { - type Item = &'a K; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<&'a K> { - self.iter.next() - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} -impl<'a, K> ExactSizeIterator for Iter<'a, K> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.iter.len() - } -} -impl<K> FusedIterator for Iter<'_, K> {} - -impl<K: fmt::Debug> fmt::Debug for Iter<'_, K> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl<K, A: Allocator + Clone> Iterator for IntoIter<K, A> { - type Item = K; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<K> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.iter.next() { - Some((k, _)) => Some(k), - None => None, - } - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} -impl<K, A: Allocator + Clone> ExactSizeIterator for IntoIter<K, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.iter.len() - } -} -impl<K, A: Allocator + Clone> FusedIterator for IntoIter<K, A> {} - -impl<K: fmt::Debug, A: Allocator + Clone> fmt::Debug for IntoIter<K, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let entries_iter = self.iter.iter().map(|(k, _)| k); - f.debug_list().entries(entries_iter).finish() - } -} - -impl<K, A: Allocator + Clone> Iterator for Drain<'_, K, A> { - type Item = K; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<K> { - // Avoid `Option::map` because it bloats LLVM IR. - match self.iter.next() { - Some((k, _)) => Some(k), - None => None, - } - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} -impl<K, A: Allocator + Clone> ExactSizeIterator for Drain<'_, K, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn len(&self) -> usize { - self.iter.len() - } -} -impl<K, A: Allocator + Clone> FusedIterator for Drain<'_, K, A> {} - -impl<K: fmt::Debug, A: Allocator + Clone> fmt::Debug for Drain<'_, K, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let entries_iter = self.iter.iter().map(|(k, _)| k); - f.debug_list().entries(entries_iter).finish() - } -} - -impl<'a, K, F, A: Allocator + Clone> Drop for DrainFilter<'a, K, F, A> -where - F: FnMut(&K) -> bool, -{ - #[cfg_attr(feature = "inline-more", inline)] - fn drop(&mut self) { - while let Some(item) = self.next() { - let guard = ConsumeAllOnDrop(self); - drop(item); - mem::forget(guard); - } - } -} - -impl<K, F, A: Allocator + Clone> Iterator for DrainFilter<'_, K, F, A> -where - F: FnMut(&K) -> bool, -{ - type Item = K; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<Self::Item> { - let f = &mut self.f; - let (k, _) = self.inner.next(&mut |k, _| f(k))?; - Some(k) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - (0, self.inner.iter.size_hint().1) - } -} - -impl<K, F, A: Allocator + Clone> FusedIterator for DrainFilter<'_, K, F, A> where - F: FnMut(&K) -> bool -{ -} - -impl<T, S, A: Allocator + Clone> Clone for Intersection<'_, T, S, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Intersection { - iter: self.iter.clone(), - ..*self - } - } -} - -impl<'a, T, S, A> Iterator for Intersection<'a, T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - type Item = &'a T; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<&'a T> { - loop { - let elt = self.iter.next()?; - if self.other.contains(elt) { - return Some(elt); - } - } - } - - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } -} - -impl<T, S, A> fmt::Debug for Intersection<'_, T, S, A> -where - T: fmt::Debug + Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl<T, S, A> FusedIterator for Intersection<'_, T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ -} - -impl<T, S, A: Allocator + Clone> Clone for Difference<'_, T, S, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Difference { - iter: self.iter.clone(), - ..*self - } - } -} - -impl<'a, T, S, A> Iterator for Difference<'a, T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - type Item = &'a T; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<&'a T> { - loop { - let elt = self.iter.next()?; - if !self.other.contains(elt) { - return Some(elt); - } - } - } - - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } -} - -impl<T, S, A> FusedIterator for Difference<'_, T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ -} - -impl<T, S, A> fmt::Debug for Difference<'_, T, S, A> -where - T: fmt::Debug + Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl<T, S, A: Allocator + Clone> Clone for SymmetricDifference<'_, T, S, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - SymmetricDifference { - iter: self.iter.clone(), - } - } -} - -impl<'a, T, S, A> Iterator for SymmetricDifference<'a, T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - type Item = &'a T; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<&'a T> { - self.iter.next() - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -impl<T, S, A> FusedIterator for SymmetricDifference<'_, T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ -} - -impl<T, S, A> fmt::Debug for SymmetricDifference<'_, T, S, A> -where - T: fmt::Debug + Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl<T, S, A: Allocator + Clone> Clone for Union<'_, T, S, A> { - #[cfg_attr(feature = "inline-more", inline)] - fn clone(&self) -> Self { - Union { - iter: self.iter.clone(), - } - } -} - -impl<T, S, A> FusedIterator for Union<'_, T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ -} - -impl<T, S, A> fmt::Debug for Union<'_, T, S, A> -where - T: fmt::Debug + Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() - } -} - -impl<'a, T, S, A> Iterator for Union<'a, T, S, A> -where - T: Eq + Hash, - S: BuildHasher, - A: Allocator + Clone, -{ - type Item = &'a T; - - #[cfg_attr(feature = "inline-more", inline)] - fn next(&mut self) -> Option<&'a T> { - self.iter.next() - } - #[cfg_attr(feature = "inline-more", inline)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -/// A view into a single entry in a set, which may either be vacant or occupied. -/// -/// This `enum` is constructed from the [`entry`] method on [`HashSet`]. -/// -/// [`HashSet`]: struct.HashSet.html -/// [`entry`]: struct.HashSet.html#method.entry -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_set::{Entry, HashSet, OccupiedEntry}; -/// -/// let mut set = HashSet::new(); -/// set.extend(["a", "b", "c"]); -/// assert_eq!(set.len(), 3); -/// -/// // Existing value (insert) -/// let entry: Entry<_, _> = set.entry("a"); -/// let _raw_o: OccupiedEntry<_, _> = entry.insert(); -/// assert_eq!(set.len(), 3); -/// // Nonexistent value (insert) -/// set.entry("d").insert(); -/// -/// // Existing value (or_insert) -/// set.entry("b").or_insert(); -/// // Nonexistent value (or_insert) -/// set.entry("e").or_insert(); -/// -/// println!("Our HashSet: {:?}", set); -/// -/// let mut vec: Vec<_> = set.iter().copied().collect(); -/// // The `Iter` iterator produces items in arbitrary order, so the -/// // items must be sorted to test them against a sorted array. -/// vec.sort_unstable(); -/// assert_eq!(vec, ["a", "b", "c", "d", "e"]); -/// ``` -pub enum Entry<'a, T, S, A = Global> -where - A: Allocator + Clone, -{ - /// An occupied entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_set::{Entry, HashSet}; - /// let mut set: HashSet<_> = ["a", "b"].into(); - /// - /// match set.entry("a") { - /// Entry::Vacant(_) => unreachable!(), - /// Entry::Occupied(_) => { } - /// } - /// ``` - Occupied(OccupiedEntry<'a, T, S, A>), - - /// A vacant entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_set::{Entry, HashSet}; - /// let mut set: HashSet<&str> = HashSet::new(); - /// - /// match set.entry("a") { - /// Entry::Occupied(_) => unreachable!(), - /// Entry::Vacant(_) => { } - /// } - /// ``` - Vacant(VacantEntry<'a, T, S, A>), -} - -impl<T: fmt::Debug, S, A: Allocator + Clone> fmt::Debug for Entry<'_, T, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), - Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), - } - } -} - -/// A view into an occupied entry in a `HashSet`. -/// It is part of the [`Entry`] enum. -/// -/// [`Entry`]: enum.Entry.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_set::{Entry, HashSet, OccupiedEntry}; -/// -/// let mut set = HashSet::new(); -/// set.extend(["a", "b", "c"]); -/// -/// let _entry_o: OccupiedEntry<_, _> = set.entry("a").insert(); -/// assert_eq!(set.len(), 3); -/// -/// // Existing key -/// match set.entry("a") { -/// Entry::Vacant(_) => unreachable!(), -/// Entry::Occupied(view) => { -/// assert_eq!(view.get(), &"a"); -/// } -/// } -/// -/// assert_eq!(set.len(), 3); -/// -/// // Existing key (take) -/// match set.entry("c") { -/// Entry::Vacant(_) => unreachable!(), -/// Entry::Occupied(view) => { -/// assert_eq!(view.remove(), "c"); -/// } -/// } -/// assert_eq!(set.get(&"c"), None); -/// assert_eq!(set.len(), 2); -/// ``` -pub struct OccupiedEntry<'a, T, S, A: Allocator + Clone = Global> { - inner: map::OccupiedEntry<'a, T, (), S, A>, -} - -impl<T: fmt::Debug, S, A: Allocator + Clone> fmt::Debug for OccupiedEntry<'_, T, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OccupiedEntry") - .field("value", self.get()) - .finish() - } -} - -/// A view into a vacant entry in a `HashSet`. -/// It is part of the [`Entry`] enum. -/// -/// [`Entry`]: enum.Entry.html -/// -/// # Examples -/// -/// ``` -/// use hashbrown::hash_set::{Entry, HashSet, VacantEntry}; -/// -/// let mut set = HashSet::<&str>::new(); -/// -/// let entry_v: VacantEntry<_, _> = match set.entry("a") { -/// Entry::Vacant(view) => view, -/// Entry::Occupied(_) => unreachable!(), -/// }; -/// entry_v.insert(); -/// assert!(set.contains("a") && set.len() == 1); -/// -/// // Nonexistent key (insert) -/// match set.entry("b") { -/// Entry::Vacant(view) => view.insert(), -/// Entry::Occupied(_) => unreachable!(), -/// } -/// assert!(set.contains("b") && set.len() == 2); -/// ``` -pub struct VacantEntry<'a, T, S, A: Allocator + Clone = Global> { - inner: map::VacantEntry<'a, T, (), S, A>, -} - -impl<T: fmt::Debug, S, A: Allocator + Clone> fmt::Debug for VacantEntry<'_, T, S, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("VacantEntry").field(self.get()).finish() - } -} - -impl<'a, T, S, A: Allocator + Clone> Entry<'a, T, S, A> { - /// Sets the value of the entry, and returns an OccupiedEntry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<&str> = HashSet::new(); - /// let entry = set.entry("horseyland").insert(); - /// - /// assert_eq!(entry.get(), &"horseyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self) -> OccupiedEntry<'a, T, S, A> - where - T: Hash, - S: BuildHasher, - { - match self { - Entry::Occupied(entry) => entry, - Entry::Vacant(entry) => entry.insert_entry(), - } - } - - /// Ensures a value is in the entry by inserting if it was vacant. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<&str> = HashSet::new(); - /// - /// // nonexistent key - /// set.entry("poneyland").or_insert(); - /// assert!(set.contains("poneyland")); - /// - /// // existing key - /// set.entry("poneyland").or_insert(); - /// assert!(set.contains("poneyland")); - /// assert_eq!(set.len(), 1); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn or_insert(self) - where - T: Hash, - S: BuildHasher, - { - if let Entry::Vacant(entry) = self { - entry.insert(); - } - } - - /// Returns a reference to this entry's value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<&str> = HashSet::new(); - /// set.entry("poneyland").or_insert(); - /// // existing key - /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); - /// // nonexistent key - /// assert_eq!(set.entry("horseland").get(), &"horseland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get(&self) -> &T { - match *self { - Entry::Occupied(ref entry) => entry.get(), - Entry::Vacant(ref entry) => entry.get(), - } - } -} - -impl<T, S, A: Allocator + Clone> OccupiedEntry<'_, T, S, A> { - /// Gets a reference to the value in the entry. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_set::{Entry, HashSet}; - /// - /// let mut set: HashSet<&str> = HashSet::new(); - /// set.entry("poneyland").or_insert(); - /// - /// match set.entry("poneyland") { - /// Entry::Vacant(_) => panic!(), - /// Entry::Occupied(entry) => assert_eq!(entry.get(), &"poneyland"), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get(&self) -> &T { - self.inner.key() - } - - /// Takes the value out of the entry, and returns it. - /// Keeps the allocated memory for reuse. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_set::Entry; - /// - /// let mut set: HashSet<&str> = HashSet::new(); - /// // The set is empty - /// assert!(set.is_empty() && set.capacity() == 0); - /// - /// set.entry("poneyland").or_insert(); - /// let capacity_before_remove = set.capacity(); - /// - /// if let Entry::Occupied(o) = set.entry("poneyland") { - /// assert_eq!(o.remove(), "poneyland"); - /// } - /// - /// assert_eq!(set.contains("poneyland"), false); - /// // Now set hold none elements but capacity is equal to the old one - /// assert!(set.len() == 0 && set.capacity() == capacity_before_remove); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn remove(self) -> T { - self.inner.remove_entry().0 - } - - /// Replaces the entry, returning the old value. The new value in the hash map will be - /// the value used to create this entry. - /// - /// # Panics - /// - /// Will panic if this OccupiedEntry was created through [`Entry::insert`]. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_set::{Entry, HashSet}; - /// use std::rc::Rc; - /// - /// let mut set: HashSet<Rc<String>> = HashSet::new(); - /// let key_one = Rc::new("Stringthing".to_string()); - /// let key_two = Rc::new("Stringthing".to_string()); - /// - /// set.insert(key_one.clone()); - /// assert!(Rc::strong_count(&key_one) == 2 && Rc::strong_count(&key_two) == 1); - /// - /// match set.entry(key_two.clone()) { - /// Entry::Occupied(entry) => { - /// let old_key: Rc<String> = entry.replace(); - /// assert!(Rc::ptr_eq(&key_one, &old_key)); - /// } - /// Entry::Vacant(_) => panic!(), - /// } - /// - /// assert!(Rc::strong_count(&key_one) == 1 && Rc::strong_count(&key_two) == 2); - /// assert!(set.contains(&"Stringthing".to_owned())); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn replace(self) -> T { - self.inner.replace_key() - } -} - -impl<'a, T, S, A: Allocator + Clone> VacantEntry<'a, T, S, A> { - /// Gets a reference to the value that would be used when inserting - /// through the `VacantEntry`. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// - /// let mut set: HashSet<&str> = HashSet::new(); - /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn get(&self) -> &T { - self.inner.key() - } - - /// Take ownership of the value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::hash_set::{Entry, HashSet}; - /// - /// let mut set: HashSet<&str> = HashSet::new(); - /// - /// match set.entry("poneyland") { - /// Entry::Occupied(_) => panic!(), - /// Entry::Vacant(v) => assert_eq!(v.into_value(), "poneyland"), - /// } - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn into_value(self) -> T { - self.inner.into_key() - } - - /// Sets the value of the entry with the VacantEntry's value. - /// - /// # Examples - /// - /// ``` - /// use hashbrown::HashSet; - /// use hashbrown::hash_set::Entry; - /// - /// let mut set: HashSet<&str> = HashSet::new(); - /// - /// if let Entry::Vacant(o) = set.entry("poneyland") { - /// o.insert(); - /// } - /// assert!(set.contains("poneyland")); - /// ``` - #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self) - where - T: Hash, - S: BuildHasher, - { - self.inner.insert(()); - } - - #[cfg_attr(feature = "inline-more", inline)] - fn insert_entry(self) -> OccupiedEntry<'a, T, S, A> - where - T: Hash, - S: BuildHasher, - { - OccupiedEntry { - inner: self.inner.insert_entry(()), - } - } -} - -#[allow(dead_code)] -fn assert_covariance() { - fn set<'new>(v: HashSet<&'static str>) -> HashSet<&'new str> { - v - } - fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { - v - } - fn into_iter<'new, A: Allocator + Clone>( - v: IntoIter<&'static str, A>, - ) -> IntoIter<&'new str, A> { - v - } - fn difference<'a, 'new, A: Allocator + Clone>( - v: Difference<'a, &'static str, DefaultHashBuilder, A>, - ) -> Difference<'a, &'new str, DefaultHashBuilder, A> { - v - } - fn symmetric_difference<'a, 'new, A: Allocator + Clone>( - v: SymmetricDifference<'a, &'static str, DefaultHashBuilder, A>, - ) -> SymmetricDifference<'a, &'new str, DefaultHashBuilder, A> { - v - } - fn intersection<'a, 'new, A: Allocator + Clone>( - v: Intersection<'a, &'static str, DefaultHashBuilder, A>, - ) -> Intersection<'a, &'new str, DefaultHashBuilder, A> { - v - } - fn union<'a, 'new, A: Allocator + Clone>( - v: Union<'a, &'static str, DefaultHashBuilder, A>, - ) -> Union<'a, &'new str, DefaultHashBuilder, A> { - v - } - fn drain<'new, A: Allocator + Clone>( - d: Drain<'static, &'static str, A>, - ) -> Drain<'new, &'new str, A> { - d - } -} - -#[cfg(test)] -mod test_set { - use super::super::map::DefaultHashBuilder; - use super::HashSet; - use std::vec::Vec; - - #[test] - fn test_zero_capacities() { - type HS = HashSet<i32>; - - let s = HS::new(); - assert_eq!(s.capacity(), 0); - - let s = HS::default(); - assert_eq!(s.capacity(), 0); - - let s = HS::with_hasher(DefaultHashBuilder::default()); - assert_eq!(s.capacity(), 0); - - let s = HS::with_capacity(0); - assert_eq!(s.capacity(), 0); - - let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default()); - assert_eq!(s.capacity(), 0); - - let mut s = HS::new(); - s.insert(1); - s.insert(2); - s.remove(&1); - s.remove(&2); - s.shrink_to_fit(); - assert_eq!(s.capacity(), 0); - - let mut s = HS::new(); - s.reserve(0); - assert_eq!(s.capacity(), 0); - } - - #[test] - fn test_disjoint() { - let mut xs = HashSet::new(); - let mut ys = HashSet::new(); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(5)); - assert!(ys.insert(11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.is_disjoint(&ys)); - assert!(!ys.is_disjoint(&xs)); - } - - #[test] - fn test_subset_and_superset() { - let mut a = HashSet::new(); - assert!(a.insert(0)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = HashSet::new(); - assert!(b.insert(0)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(!b.is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(b.is_superset(&a)); - } - - #[test] - fn test_iterate() { - let mut a = HashSet::new(); - for i in 0..32 { - assert!(a.insert(i)); - } - let mut observed: u32 = 0; - for k in &a { - observed |= 1 << *k; - } - assert_eq!(observed, 0xFFFF_FFFF); - } - - #[test] - fn test_intersection() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - assert!(a.insert(-5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(-9)); - assert!(b.insert(-42)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let mut i = 0; - let expected = [3, 5, 11, 77]; - for x in a.intersection(&b) { - assert!(expected.contains(x)); - i += 1; - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - - let mut i = 0; - let expected = [1, 5, 11]; - for x in a.difference(&b) { - assert!(expected.contains(x)); - i += 1; - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_symmetric_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(-2)); - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(22)); - - let mut i = 0; - let expected = [-2, 1, 5, 11, 14, 22]; - for x in a.symmetric_difference(&b) { - assert!(expected.contains(x)); - i += 1; - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_union() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(16)); - assert!(a.insert(19)); - assert!(a.insert(24)); - - assert!(b.insert(-2)); - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let mut i = 0; - let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; - for x in a.union(&b) { - assert!(expected.contains(x)); - i += 1; - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_from_map() { - let mut a = crate::HashMap::new(); - a.insert(1, ()); - a.insert(2, ()); - a.insert(3, ()); - a.insert(4, ()); - - let a: HashSet<_> = a.into(); - - assert_eq!(a.len(), 4); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - } - - #[test] - fn test_from_iter() { - let xs = [1, 2, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: HashSet<_> = xs.iter().copied().collect(); - - for x in &xs { - assert!(set.contains(x)); - } - - assert_eq!(set.iter().len(), xs.len() - 1); - } - - #[test] - fn test_move_iter() { - let hs = { - let mut hs = HashSet::new(); - - hs.insert('a'); - hs.insert('b'); - - hs - }; - - let v = hs.into_iter().collect::<Vec<char>>(); - assert!(v == ['a', 'b'] || v == ['b', 'a']); - } - - #[test] - fn test_eq() { - // These constants once happened to expose a bug in insert(). - // I'm keeping them around to prevent a regression. - let mut s1 = HashSet::new(); - - s1.insert(1); - s1.insert(2); - s1.insert(3); - - let mut s2 = HashSet::new(); - - s2.insert(1); - s2.insert(2); - - assert!(s1 != s2); - - s2.insert(3); - - assert_eq!(s1, s2); - } - - #[test] - fn test_show() { - let mut set = HashSet::new(); - let empty = HashSet::<i32>::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{:?}", set); - - assert!(set_str == "{1, 2}" || set_str == "{2, 1}"); - assert_eq!(format!("{:?}", empty), "{}"); - } - - #[test] - fn test_trivial_drain() { - let mut s = HashSet::<i32>::new(); - for _ in s.drain() {} - assert!(s.is_empty()); - drop(s); - - let mut s = HashSet::<i32>::new(); - drop(s.drain()); - assert!(s.is_empty()); - } - - #[test] - fn test_drain() { - let mut s: HashSet<_> = (1..100).collect(); - - // try this a bunch of times to make sure we don't screw up internal state. - for _ in 0..20 { - assert_eq!(s.len(), 99); - - { - let mut last_i = 0; - let mut d = s.drain(); - for (i, x) in d.by_ref().take(50).enumerate() { - last_i = i; - assert!(x != 0); - } - assert_eq!(last_i, 49); - } - - for _ in &s { - panic!("s should be empty!"); - } - - // reset to try again. - s.extend(1..100); - } - } - - #[test] - fn test_replace() { - use core::hash; - - #[derive(Debug)] - struct Foo(&'static str, i32); - - impl PartialEq for Foo { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl Eq for Foo {} - - impl hash::Hash for Foo { - fn hash<H: hash::Hasher>(&self, h: &mut H) { - self.0.hash(h); - } - } - - let mut s = HashSet::new(); - assert_eq!(s.replace(Foo("a", 1)), None); - assert_eq!(s.len(), 1); - assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1))); - assert_eq!(s.len(), 1); - - let mut it = s.iter(); - assert_eq!(it.next(), Some(&Foo("a", 2))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_extend_ref() { - let mut a = HashSet::new(); - a.insert(1); - - a.extend([2, 3, 4]); - - assert_eq!(a.len(), 4); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - - let mut b = HashSet::new(); - b.insert(5); - b.insert(6); - - a.extend(&b); - - assert_eq!(a.len(), 6); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - assert!(a.contains(&5)); - assert!(a.contains(&6)); - } - - #[test] - fn test_retain() { - let xs = [1, 2, 3, 4, 5, 6]; - let mut set: HashSet<i32> = xs.iter().copied().collect(); - set.retain(|&k| k % 2 == 0); - assert_eq!(set.len(), 3); - assert!(set.contains(&2)); - assert!(set.contains(&4)); - assert!(set.contains(&6)); - } - - #[test] - fn test_drain_filter() { - { - let mut set: HashSet<i32> = (0..8).collect(); - let drained = set.drain_filter(|&k| k % 2 == 0); - let mut out = drained.collect::<Vec<_>>(); - out.sort_unstable(); - assert_eq!(vec![0, 2, 4, 6], out); - assert_eq!(set.len(), 4); - } - { - let mut set: HashSet<i32> = (0..8).collect(); - drop(set.drain_filter(|&k| k % 2 == 0)); - assert_eq!(set.len(), 4, "Removes non-matching items on drop"); - } - } - - #[test] - fn test_const_with_hasher() { - use core::hash::BuildHasher; - use std::collections::hash_map::DefaultHasher; - - #[derive(Clone)] - struct MyHasher; - impl BuildHasher for MyHasher { - type Hasher = DefaultHasher; - - fn build_hasher(&self) -> DefaultHasher { - DefaultHasher::new() - } - } - - const EMPTY_SET: HashSet<u32, MyHasher> = HashSet::with_hasher(MyHasher); - - let mut set = EMPTY_SET; - set.insert(19); - assert!(set.contains(&19)); - } - - #[test] - fn rehash_in_place() { - let mut set = HashSet::new(); - - for i in 0..224 { - set.insert(i); - } - - assert_eq!( - set.capacity(), - 224, - "The set must be at or close to capacity to trigger a re hashing" - ); - - for i in 100..1400 { - set.remove(&(i - 100)); - set.insert(i); - } - } -} |