Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Debug, FusedIterator and Iterator::fold for all HashTable iterators #561

Merged
merged 1 commit into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great - did you mean to propagate that up too?

#[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
143 changes: 128 additions & 15 deletions src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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,
}
}

Expand Down 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 @@ -2061,7 +2076,17 @@ impl<T> FusedIterator for IterMut<'_, T> {}
/// [`HashTable`]: struct.HashTable.html
pub struct IterHash<'a, T> {
inner: RawIterHash<T>,
_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> {
Expand All @@ -2074,6 +2099,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()) })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is okay, but the inner RawIterHash isn't doing anything special for fold.
(Ditto for IterHashMut, and Drain's RawDrain.)

}
}

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 @@ -2086,7 +2142,17 @@ impl<'a, T> Iterator for IterHash<'a, T> {
/// [`HashTable`]: struct.HashTable.html
pub struct IterHashMut<'a, T> {
inner: RawIterHash<T>,
_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> {
Expand All @@ -2099,6 +2165,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 +2217,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 +2252,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 +2278,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
Loading