From 7af86aba43f8a56096394b6c4ec440638ace64c3 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 20 Sep 2024 13:10:29 +0100 Subject: [PATCH] Implement `Debug`, `FusedIterator` and `Iterator::fold` for all `HashTable` iterators --- src/raw/mod.rs | 23 ++++++++ src/table.rs | 143 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 151 insertions(+), 15 deletions(-) diff --git a/src/raw/mod.rs b/src/raw/mod.rs index 58a0a9178..2c6392181 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -163,6 +163,7 @@ fn h2(hash: u64) -> u8 { /// /// Proof that the probe will visit every group in the table: /// +#[derive(Clone)] struct ProbeSeq { pos: usize, stride: usize, @@ -4070,6 +4071,7 @@ pub struct RawIterHash { _marker: PhantomData, } +#[derive(Clone)] struct RawIterHashInner { // See `RawTableInner`'s corresponding fields for details. // We can't store a `*const RawTableInner` as it would get @@ -4099,6 +4101,27 @@ impl RawIterHash { } } +impl Clone for RawIterHash { + #[cfg_attr(feature = "inline-more", inline)] + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + _marker: PhantomData, + } + } +} + +impl Default for RawIterHash { + #[cfg_attr(feature = "inline-more", inline)] + fn default() -> Self { + Self { + // SAFETY: Because the table is static, it always outlives the iter. + inner: unsafe { RawIterHashInner::new(&RawTableInner::NEW, 0) }, + _marker: PhantomData, + } + } +} + impl RawIterHashInner { #[cfg_attr(feature = "inline-more", inline)] unsafe fn new(table: &RawTableInner, hash: u64) -> Self { diff --git a/src/table.rs b/src/table.rs index 0b8b66424..8f9530404 100644 --- a/src/table.rs +++ b/src/table.rs @@ -776,7 +776,7 @@ where pub fn iter_hash(&self, hash: u64) -> IterHash<'_, T> { IterHash { inner: unsafe { self.raw.iter_hash(hash) }, - _marker: PhantomData, + marker: PhantomData, } } @@ -829,7 +829,7 @@ where pub fn iter_hash_mut(&mut self, hash: u64) -> IterHashMut<'_, T> { IterHashMut { inner: unsafe { self.raw.iter_hash(hash) }, - _marker: PhantomData, + marker: PhantomData, } } @@ -1946,6 +1946,7 @@ impl<'a, T> Default for Iter<'a, T> { } } } + impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; @@ -2051,6 +2052,20 @@ impl ExactSizeIterator for IterMut<'_, T> { impl FusedIterator for IterMut<'_, T> {} +impl fmt::Debug for IterMut<'_, T> +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries(Iter { + inner: self.inner.clone(), + marker: PhantomData, + }) + .finish() + } +} + /// An iterator over the entries of a `HashTable` that could match a given hash. /// The iterator element type is `&'a T`. /// @@ -2061,7 +2076,17 @@ impl FusedIterator for IterMut<'_, T> {} /// [`HashTable`]: struct.HashTable.html pub struct IterHash<'a, T> { inner: RawIterHash, - _marker: PhantomData<&'a T>, + marker: PhantomData<&'a T>, +} + +impl<'a, T> Default for IterHash<'a, T> { + #[cfg_attr(feature = "inline-more", inline)] + fn default() -> Self { + IterHash { + inner: Default::default(), + marker: PhantomData, + } + } } impl<'a, T> Iterator for IterHash<'a, T> { @@ -2074,6 +2099,37 @@ impl<'a, T> Iterator for IterHash<'a, T> { None => None, } } + + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner + .fold(init, |acc, bucket| unsafe { f(acc, bucket.as_ref()) }) + } +} + +impl FusedIterator for IterHash<'_, T> {} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +impl<'a, T> Clone for IterHash<'a, T> { + #[cfg_attr(feature = "inline-more", inline)] + fn clone(&self) -> IterHash<'a, T> { + IterHash { + inner: self.inner.clone(), + marker: PhantomData, + } + } +} + +impl fmt::Debug for IterHash<'_, T> +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } } /// A mutable iterator over the entries of a `HashTable` that could match a given hash. @@ -2086,7 +2142,17 @@ impl<'a, T> Iterator for IterHash<'a, T> { /// [`HashTable`]: struct.HashTable.html pub struct IterHashMut<'a, T> { inner: RawIterHash, - _marker: PhantomData<&'a mut T>, + marker: PhantomData<&'a mut T>, +} + +impl<'a, T> Default for IterHashMut<'a, T> { + #[cfg_attr(feature = "inline-more", inline)] + fn default() -> Self { + IterHashMut { + inner: Default::default(), + marker: PhantomData, + } + } } impl<'a, T> Iterator for IterHashMut<'a, T> { @@ -2099,6 +2165,31 @@ impl<'a, T> Iterator for IterHashMut<'a, T> { None => None, } } + + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner + .fold(init, |acc, bucket| unsafe { f(acc, bucket.as_mut()) }) + } +} + +impl FusedIterator for IterHashMut<'_, T> {} + +impl fmt::Debug for IterHashMut<'_, T> +where + T: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries(IterHash { + inner: self.inner.clone(), + marker: PhantomData, + }) + .finish() + } } /// An owning iterator over the entries of a `HashTable` in arbitrary order. @@ -2126,6 +2217,7 @@ impl Default for IntoIter { } } } + impl Iterator for IntoIter where A: Allocator, @@ -2160,6 +2252,21 @@ where impl FusedIterator for IntoIter where A: Allocator {} +impl fmt::Debug for IntoIter +where + T: fmt::Debug, + A: Allocator, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries(Iter { + inner: self.inner.iter(), + marker: PhantomData, + }) + .finish() + } +} + /// A draining iterator over the items of a `HashTable`. /// /// This `struct` is created by the [`drain`] method on [`HashTable`]. @@ -2171,36 +2278,42 @@ pub struct Drain<'a, T, A: Allocator = Global> { inner: RawDrain<'a, T, A>, } -impl Drain<'_, T, A> { - /// Returns a iterator of references over the remaining items. - fn iter(&self) -> Iter<'_, T> { - Iter { - inner: self.inner.iter(), - marker: PhantomData, - } - } -} - impl Iterator for Drain<'_, T, A> { type Item = T; fn next(&mut self) -> Option { self.inner.next() } + fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, f) + } } + impl ExactSizeIterator for Drain<'_, T, A> { fn len(&self) -> usize { self.inner.len() } } + impl FusedIterator for Drain<'_, T, A> {} impl fmt::Debug for Drain<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() + f.debug_list() + .entries(Iter { + inner: self.inner.iter(), + marker: PhantomData, + }) + .finish() } }