Skip to content

Commit

Permalink
Merge pull request #19770 from csouth3/iterator-wrapperstructs
Browse files Browse the repository at this point in the history
Use wrapper structs for iterators in BTreeMap/Set and HashMap/Set

Reviewed-by: Gankro
  • Loading branch information
bors committed Dec 14, 2014
2 parents a198d8a + e38de8a commit b5fbfe2
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 69 deletions.
34 changes: 28 additions & 6 deletions src/libcollections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use std::hash::{Writer, Hash};
use core::default::Default;
use core::{iter, fmt, mem};
use core::fmt::Show;
use core::iter::Map;

use ring_buf::RingBuf;

Expand Down Expand Up @@ -110,12 +111,14 @@ pub struct MoveEntries<K, V> {
}

/// An iterator over a BTreeMap's keys.
pub type Keys<'a, K, V> =
iter::Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>;
pub struct Keys<'a, K: 'a, V: 'a> {
inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
}

/// An iterator over a BTreeMap's values.
pub type Values<'a, K, V> =
iter::Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>;
pub struct Values<'a, K: 'a, V: 'a> {
inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
}

/// A view into a single entry in a map, which may either be vacant or occupied.
pub enum Entry<'a, K:'a, V:'a> {
Expand Down Expand Up @@ -1054,6 +1057,25 @@ impl<K, V> DoubleEndedIterator<(K, V)> for MoveEntries<K, V> {
impl<K, V> ExactSizeIterator<(K, V)> for MoveEntries<K, V> {}


impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
impl<'a, K, V> DoubleEndedIterator<&'a K> for Keys<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K)> { self.inner.next_back() }
}
impl<'a, K, V> ExactSizeIterator<&'a K> for Keys<'a, K, V> {}


impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
impl<'a, K, V> DoubleEndedIterator<&'a V> for Values<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a V)> { self.inner.next_back() }
}
impl<'a, K, V> ExactSizeIterator<&'a V> for Values<'a, K, V> {}


impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
/// Sets the value of the entry with the VacantEntry's key,
Expand Down Expand Up @@ -1204,7 +1226,7 @@ impl<K, V> BTreeMap<K, V> {
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
fn first<A, B>((a, _): (A, B)) -> A { a }

self.iter().map(first)
Keys { inner: self.iter().map(first) }
}

/// Gets an iterator over the values of the map.
Expand All @@ -1225,7 +1247,7 @@ impl<K, V> BTreeMap<K, V> {
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
fn second<A, B>((_, b): (A, B)) -> B { b }

self.iter().map(second)
Values { inner: self.iter().map(second) }
}

/// Return the number of elements in the map.
Expand Down
34 changes: 28 additions & 6 deletions src/libcollections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::hash::Hash;
use core::borrow::BorrowFrom;
use core::default::Default;
use core::{iter, fmt};
use core::iter::Peekable;
use core::iter::{Peekable, Map};
use core::fmt::Show;

// FIXME(conventions): implement bounded iterators
Expand All @@ -33,11 +33,14 @@ pub struct BTreeSet<T>{
}

/// An iterator over a BTreeSet's items.
pub type Items<'a, T> = Keys<'a, T, ()>;
pub struct Items<'a, T: 'a> {
iter: Keys<'a, T, ()>
}

/// An owning iterator over a BTreeSet's items.
pub type MoveItems<T> =
iter::Map<(T, ()), T, MoveEntries<T, ()>, fn((T, ())) -> T>;
pub struct MoveItems<T> {
iter: Map<(T, ()), T, MoveEntries<T, ()>, fn((T, ())) -> T>
}

/// A lazy iterator producing elements in the set difference (in-order).
pub struct DifferenceItems<'a, T:'a> {
Expand Down Expand Up @@ -82,15 +85,15 @@ impl<T> BTreeSet<T> {
/// Gets an iterator over the BTreeSet's contents.
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn iter<'a>(&'a self) -> Items<'a, T> {
self.map.keys()
Items { iter: self.map.keys() }
}

/// Gets an iterator for moving out the BtreeSet's contents.
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn into_iter(self) -> MoveItems<T> {
fn first<A, B>((a, _): (A, B)) -> A { a }

self.map.into_iter().map(first)
MoveItems { iter: self.map.into_iter().map(first) }
}
}

Expand Down Expand Up @@ -505,6 +508,25 @@ impl<T: Show> Show for BTreeSet<T> {
}
}

impl<'a, T> Iterator<&'a T> for Items<'a, T> {
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
impl<'a, T> DoubleEndedIterator<&'a T> for Items<'a, T> {
fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back() }
}
impl<'a, T> ExactSizeIterator<&'a T> for Items<'a, T> {}


impl<T> Iterator<T> for MoveItems<T> {
fn next(&mut self) -> Option<T> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
impl<T> DoubleEndedIterator<T> for MoveItems<T> {
fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
}
impl<T> ExactSizeIterator<T> for MoveItems<T> {}

/// Compare `x` and `y`, but return `short` if x is None and `long` if y is None
fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>,
short: Ordering, long: Ordering) -> Ordering {
Expand Down
64 changes: 29 additions & 35 deletions src/libstd/collections/hash/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use cmp::{max, Eq, Equiv, PartialEq};
use default::Default;
use fmt::{mod, Show};
use hash::{Hash, Hasher, RandomSipHasher};
use iter::{mod, Iterator, IteratorExt, FromIterator, Extend};
use iter::{mod, Iterator, IteratorExt, FromIterator, Extend, Map};
use kinds::Sized;
use mem::{mod, replace};
use num::{Int, UnsignedInt};
Expand Down Expand Up @@ -859,7 +859,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
pub fn keys(&self) -> Keys<K, V> {
fn first<A, B>((a, _): (A, B)) -> A { a }

self.iter().map(first)
Keys { inner: self.iter().map(first) }
}

/// An iterator visiting all values in arbitrary order.
Expand All @@ -883,7 +883,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
pub fn values(&self) -> Values<K, V> {
fn second<A, B>((_, b): (A, B)) -> B { b }

self.iter().map(second)
Values { inner: self.iter().map(second) }
}

/// An iterator visiting all key-value pairs in arbitrary order.
Expand Down Expand Up @@ -1335,6 +1335,16 @@ pub struct MoveEntries<K, V> {
>
}

/// HashMap keys iterator
pub struct Keys<'a, K: 'a, V: 'a> {
inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
}

/// HashMap values iterator
pub struct Values<'a, K: 'a, V: 'a> {
inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
}

/// A view into a single occupied location in a HashMap
pub struct OccupiedEntry<'a, K:'a, V:'a> {
elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
Expand Down Expand Up @@ -1365,36 +1375,28 @@ enum VacantEntryState<K, V, M> {
}

impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a V)> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.inner.size_hint()
}
#[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}

impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.inner.size_hint()
}
#[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}

impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
#[inline]
fn next(&mut self) -> Option<(K, V)> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.inner.size_hint()
}
#[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}

impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
#[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}

impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
#[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}

impl<'a, K, V> OccupiedEntry<'a, K, V> {
Expand Down Expand Up @@ -1448,14 +1450,6 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
}
}

/// HashMap keys iterator
pub type Keys<'a, K, V> =
iter::Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>;

/// HashMap values iterator
pub type Values<'a, K, V> =
iter::Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>;

impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> {
let (lower, _) = iter.size_hint();
Expand Down
82 changes: 60 additions & 22 deletions src/libstd/collections/hash/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ use default::Default;
use fmt::Show;
use fmt;
use hash::{Hash, Hasher, RandomSipHasher};
use iter::{Iterator, IteratorExt, FromIterator, FilterMap, Chain, Repeat, Zip, Extend, repeat};
use iter;
use option::Option::{Some, None, mod};
use iter::{Iterator, IteratorExt, FromIterator, Map, FilterMap, Chain, Repeat, Zip, Extend, repeat};
use result::Result::{Ok, Err};

use super::map::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY};
use super::map::{HashMap, MoveEntries, Keys, INITIAL_CAPACITY};

// FIXME(conventions): implement BitOr, BitAnd, BitXor, and Sub

Expand Down Expand Up @@ -252,7 +251,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
self.map.keys()
SetItems { iter: self.map.keys() }
}

/// Creates a consuming iterator, that is, one that moves each value out
Expand All @@ -279,7 +278,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
pub fn into_iter(self) -> SetMoveItems<T> {
fn first<A, B>((a, _): (A, B)) -> A { a }

self.map.into_iter().map(first)
SetMoveItems { iter: self.map.into_iter().map(first) }
}

/// Visit the values representing the difference.
Expand Down Expand Up @@ -312,7 +311,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
if !other.contains(elt) { Some(elt) } else { None }
}

repeat(other).zip(self.iter()).filter_map(filter)
SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
}

/// Visit the values representing the symmetric difference.
Expand All @@ -337,8 +336,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
-> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
self.difference(other).chain(other.difference(self))
-> SymDifferenceItems<'a, T, H> {
SymDifferenceItems { iter: self.difference(other).chain(other.difference(self)) }
}

/// Visit the values representing the intersection.
Expand Down Expand Up @@ -366,7 +365,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
if other.contains(elt) { Some(elt) } else { None }
}

repeat(other).zip(self.iter()).filter_map(filter)
SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
}

/// Visit the values representing the union.
Expand All @@ -387,9 +386,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
-> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
self.iter().chain(other.difference(self))
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> UnionItems<'a, T, H> {
UnionItems { iter: self.iter().chain(other.difference(self)) }
}

/// Return the number of elements in the set
Expand Down Expand Up @@ -617,21 +615,61 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
}

/// HashSet iterator
pub type SetItems<'a, K> =
iter::Map<(&'a K, &'a ()), &'a K, Entries<'a, K, ()>, fn((&'a K, &'a ())) -> &'a K>;
pub struct SetItems<'a, K: 'a> {
iter: Keys<'a, K, ()>
}

/// HashSet move iterator
pub type SetMoveItems<K> = iter::Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>;
pub struct SetMoveItems<K> {
iter: Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>
}

// `Repeat` is used to feed the filter closure an explicit capture
// of a reference to the other set
/// Set operations iterator
pub type SetAlgebraItems<'a, T, H> = FilterMap<
(&'a HashSet<T, H>, &'a T),
&'a T,
Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
>;
/// Set operations iterator, used directly for intersection and difference
pub struct SetAlgebraItems<'a, T: 'a, H: 'a> {
iter: FilterMap<
(&'a HashSet<T, H>, &'a T),
&'a T,
Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
>
}

/// Symmetric difference iterator.
pub struct SymDifferenceItems<'a, T: 'a, H: 'a> {
iter: Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>>
}

/// Set union iterator.
pub struct UnionItems<'a, T: 'a, H: 'a> {
iter: Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>>
}

impl<'a, K> Iterator<&'a K> for SetItems<'a, K> {
fn next(&mut self) -> Option<&'a K> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

impl<K> Iterator<K> for SetMoveItems<K> {
fn next(&mut self) -> Option<K> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

impl<'a, T, H> Iterator<&'a T> for SetAlgebraItems<'a, T, H> {
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

impl<'a, T, H> Iterator<&'a T> for SymDifferenceItems<'a, T, H> {
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

impl<'a, T, H> Iterator<&'a T> for UnionItems<'a, T, H> {
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

#[cfg(test)]
mod test_set {
Expand Down

0 comments on commit b5fbfe2

Please sign in to comment.