Skip to content

Commit b9415d6

Browse files
committed
Implement fold on hash::table::{Iter,IterMut}.
Also forwards `fold` to the wrapped iterator for `HashMap` and `HashSet` iterators to actually gain something from the change.
1 parent 87af232 commit b9415d6

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

src/libstd/collections/hash/map.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,12 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
15181518
fn size_hint(&self) -> (usize, Option<usize>) {
15191519
self.inner.size_hint()
15201520
}
1521+
#[inline]
1522+
fn fold<B, F>(self, init: B, f: F) -> B where
1523+
Self: Sized, F: FnMut(B, Self::Item) -> B,
1524+
{
1525+
self.inner.fold(init, f)
1526+
}
15211527
}
15221528
#[stable(feature = "rust1", since = "1.0.0")]
15231529
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
@@ -1542,6 +1548,12 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
15421548
fn size_hint(&self) -> (usize, Option<usize>) {
15431549
self.inner.size_hint()
15441550
}
1551+
#[inline]
1552+
fn fold<B, F>(self, init: B, f: F) -> B where
1553+
Self: Sized, F: FnMut(B, Self::Item) -> B,
1554+
{
1555+
self.inner.fold(init, f)
1556+
}
15451557
}
15461558
#[stable(feature = "rust1", since = "1.0.0")]
15471559
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
@@ -1588,6 +1600,12 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
15881600
fn size_hint(&self) -> (usize, Option<usize>) {
15891601
self.inner.size_hint()
15901602
}
1603+
#[inline]
1604+
fn fold<B, F>(self, init: B, mut f: F) -> B where
1605+
Self: Sized, F: FnMut(B, Self::Item) -> B,
1606+
{
1607+
self.inner.fold(init, move |acc, (k, _)| f(acc, k))
1608+
}
15911609
}
15921610
#[stable(feature = "rust1", since = "1.0.0")]
15931611
impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
@@ -1611,6 +1629,12 @@ impl<'a, K, V> Iterator for Values<'a, K, V> {
16111629
fn size_hint(&self) -> (usize, Option<usize>) {
16121630
self.inner.size_hint()
16131631
}
1632+
#[inline]
1633+
fn fold<B, F>(self, init: B, mut f: F) -> B where
1634+
Self: Sized, F: FnMut(B, Self::Item) -> B,
1635+
{
1636+
self.inner.fold(init, move |acc, (_, v)| f(acc, v))
1637+
}
16141638
}
16151639
#[stable(feature = "rust1", since = "1.0.0")]
16161640
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
@@ -1634,6 +1658,12 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
16341658
fn size_hint(&self) -> (usize, Option<usize>) {
16351659
self.inner.size_hint()
16361660
}
1661+
#[inline]
1662+
fn fold<B, F>(self, init: B, mut f: F) -> B where
1663+
Self: Sized, F: FnMut(B, Self::Item) -> B,
1664+
{
1665+
self.inner.fold(init, move |acc, (_, v)| f(acc, v))
1666+
}
16371667
}
16381668
#[stable(feature = "map_values_mut", since = "1.10.0")]
16391669
impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {

src/libstd/collections/hash/set.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,12 @@ impl<'a, K> Iterator for Iter<'a, K> {
942942
fn size_hint(&self) -> (usize, Option<usize>) {
943943
self.iter.size_hint()
944944
}
945+
#[inline]
946+
fn fold<B, F>(self, init: B, f: F) -> B where
947+
Self: Sized, F: FnMut(B, Self::Item) -> B,
948+
{
949+
self.iter.fold(init, f)
950+
}
945951
}
946952
#[stable(feature = "rust1", since = "1.0.0")]
947953
impl<'a, K> ExactSizeIterator for Iter<'a, K> {

src/libstd/collections/hash/table.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,24 @@ impl<'a, K, V> Iterator for RawBuckets<'a, K, V> {
795795

796796
None
797797
}
798+
799+
fn fold<B, F>(self, init: B, mut f: F) -> B where
800+
Self: Sized, F: FnMut(B, Self::Item) -> B,
801+
{
802+
let mut acc = init;
803+
let RawBuckets { mut raw, hashes_end, .. } = self;
804+
while raw.hash != hashes_end {
805+
unsafe {
806+
// We are swapping out the pointer to a bucket and replacing
807+
// it with the pointer to the next one.
808+
let prev = ptr::replace(&mut raw, raw.offset(1));
809+
if *prev.hash != EMPTY_BUCKET {
810+
acc = f(acc, prev)
811+
}
812+
}
813+
}
814+
acc
815+
}
798816
}
799817

800818
/// An iterator that moves out buckets in reverse order. It leaves the table
@@ -899,6 +917,15 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
899917
fn size_hint(&self) -> (usize, Option<usize>) {
900918
(self.elems_left, Some(self.elems_left))
901919
}
920+
921+
#[inline]
922+
fn fold<B, F>(self, init: B, mut f: F) -> B where
923+
Self: Sized, F: FnMut(B, Self::Item) -> B,
924+
{
925+
self.iter.fold(init, move |acc, bucket| {
926+
f(acc, unsafe { (&(*bucket.pair).0, &(*bucket.pair).1) })
927+
})
928+
}
902929
}
903930
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
904931
fn len(&self) -> usize {
@@ -920,6 +947,16 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
920947
fn size_hint(&self) -> (usize, Option<usize>) {
921948
(self.elems_left, Some(self.elems_left))
922949
}
950+
951+
#[inline]
952+
fn fold<B, F>(self, init: B, mut f: F) -> B where
953+
Self: Sized, F: FnMut(B, Self::Item) -> B,
954+
{
955+
self.iter.fold(init, move |acc, bucket| {
956+
let pair_mut = bucket.pair as *mut (K, V);
957+
f(acc, unsafe { (&(*pair_mut).0, &mut (*pair_mut).1) })
958+
})
959+
}
923960
}
924961
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
925962
fn len(&self) -> usize {

0 commit comments

Comments
 (0)