Skip to content

Commit

Permalink
Implement Debug, FusedIterator and Iterator::fold for all `Hash…
Browse files Browse the repository at this point in the history
…Table` iterators
  • Loading branch information
Amanieu committed Sep 21, 2024
1 parent cd9a955 commit de75dfc
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 11 deletions.
23 changes: 23 additions & 0 deletions src/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ fn h2(hash: u64) -> u8 {
///
/// Proof that the probe will visit every group in the table:
/// <https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/>
#[derive(Clone)]
struct ProbeSeq {
pos: usize,
stride: usize,
Expand Down Expand Up @@ -4070,6 +4071,7 @@ pub struct RawIterHash<T> {
_marker: PhantomData<T>,
}

#[derive(Clone)]
struct RawIterHashInner {
// See `RawTableInner`'s corresponding fields for details.
// We can't store a `*const RawTableInner` as it would get
Expand Down Expand Up @@ -4099,6 +4101,27 @@ impl<T> RawIterHash<T> {
}
}

impl<T> Clone for RawIterHash<T> {
#[cfg_attr(feature = "inline-more", inline)]
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
_marker: PhantomData,
}
}
}

impl<T> Default for RawIterHash<T> {
#[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 {
Expand Down
115 changes: 104 additions & 11 deletions src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,7 @@ impl<'a, T> Default for Iter<'a, T> {
}
}
}

impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;

Expand Down Expand Up @@ -2051,6 +2052,20 @@ impl<T> ExactSizeIterator for IterMut<'_, T> {

impl<T> FusedIterator for IterMut<'_, T> {}

impl<T> 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`.
///
Expand All @@ -2074,6 +2089,37 @@ impl<'a, T> Iterator for IterHash<'a, T> {
None => None,
}
}

fn fold<B, F>(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<T> 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<T> 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.
Expand All @@ -2099,6 +2145,31 @@ impl<'a, T> Iterator for IterHashMut<'a, T> {
None => None,
}
}

fn fold<B, F>(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<T> FusedIterator for IterHashMut<'_, T> {}

impl<T> 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.
Expand Down Expand Up @@ -2126,6 +2197,7 @@ impl<T, A: Allocator> Default for IntoIter<T, A> {
}
}
}

impl<T, A> Iterator for IntoIter<T, A>
where
A: Allocator,
Expand Down Expand Up @@ -2160,6 +2232,21 @@ where

impl<T, A> FusedIterator for IntoIter<T, A> where A: Allocator {}

impl<T, A> fmt::Debug for IntoIter<T, A>
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`].
Expand All @@ -2171,36 +2258,42 @@ pub struct Drain<'a, T, A: Allocator = Global> {
inner: RawDrain<'a, T, A>,
}

impl<T, A: Allocator> 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<T, A: Allocator> Iterator for Drain<'_, T, A> {
type Item = T;

fn next(&mut self) -> Option<T> {
self.inner.next()
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}

fn fold<B, F>(self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.inner.fold(init, f)
}
}

impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
fn len(&self) -> usize {
self.inner.len()
}
}

impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}

impl<T: fmt::Debug, A: Allocator> 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()
}
}

Expand Down

0 comments on commit de75dfc

Please sign in to comment.