diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index c42eba1ffa2..fe05b48988e 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -47,6 +47,7 @@ struct Node { } /// Double-ended DList iterator +#[deriving(Clone)] pub struct DListIterator<'self, T> { priv head: &'self Link, priv tail: Rawlink>, @@ -62,6 +63,7 @@ pub struct MutDListIterator<'self, T> { } /// DList consuming iterator +#[deriving(Clone)] pub struct ConsumeIterator { priv list: DList } @@ -93,6 +95,13 @@ impl Rawlink { } } +impl Clone for Rawlink { + #[inline] + fn clone(&self) -> Rawlink { + Rawlink{p: self.p} + } +} + /// Set the .prev field on `next`, then return `Some(next)` fn link_with_prev(mut next: ~Node, prev: Rawlink>) -> Link { next.prev = prev; @@ -686,6 +695,20 @@ mod tests { assert_eq!(it.next(), None); } + #[test] + fn test_iterator_clone() { + let mut n = DList::new(); + n.push_back(2); + n.push_back(3); + n.push_back(4); + let mut it = n.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next_back(), jt.next_back()); + assert_eq!(it.next(), jt.next()); + } + #[test] fn test_iterator_double_end() { let mut n = DList::new(); diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 182ee37202a..56774560d1d 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -548,6 +548,7 @@ impl Clone for HashMap { } /// HashMap iterator +#[deriving(Clone)] pub struct HashMapIterator<'self, K, V> { priv iter: vec::VecIterator<'self, Option>>, } @@ -563,6 +564,7 @@ pub struct HashMapConsumeIterator { } /// HashSet iterator +#[deriving(Clone)] pub struct HashSetIterator<'self, K> { priv iter: vec::VecIterator<'self, Option>>, } diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index c8cde69197b..198e63f83c6 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -74,6 +74,7 @@ impl> DoubleEndedIteratorUtil for T { /// An double-ended iterator with the direction inverted // FIXME #6967: Dummy A parameter to get around type inference bug +#[deriving(Clone)] pub struct InvertIterator { priv iter: T } @@ -729,8 +730,59 @@ impl> OrdIterator for T { } } +/// A trait for iterators that are clonable. +// FIXME #6967: Dummy A parameter to get around type inference bug +pub trait ClonableIterator { + /// Repeats an iterator endlessly + /// + /// # Example + /// + /// ~~~ {.rust} + /// let a = Counter::new(1,1).take_(1); + /// let mut cy = a.cycle(); + /// assert_eq!(cy.next(), Some(1)); + /// assert_eq!(cy.next(), Some(1)); + /// ~~~ + fn cycle(self) -> CycleIterator; +} + +impl> ClonableIterator for T { + #[inline] + fn cycle(self) -> CycleIterator { + CycleIterator{orig: self.clone(), iter: self} + } +} + +/// An iterator that repeats endlessly +#[deriving(Clone)] +pub struct CycleIterator { + priv orig: T, + priv iter: T, +} + +impl> Iterator for CycleIterator { + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + None => { self.iter = self.orig.clone(); self.iter.next() } + y => y + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + // the cycle iterator is either empty or infinite + match self.orig.size_hint() { + sz @ (0, Some(0)) => sz, + (0, _) => (0, None), + _ => (uint::max_value, None) + } + } +} + /// An iterator which strings two iterators together // FIXME #6967: Dummy A parameter to get around type inference bug +#[deriving(Clone)] pub struct ChainIterator { priv a: T, priv b: U, @@ -786,6 +838,7 @@ for ChainIterator { /// An iterator which iterates two other iterators simultaneously // FIXME #6967: Dummy A & B parameters to get around type inference bug +#[deriving(Clone)] pub struct ZipIterator { priv a: T, priv b: U @@ -939,6 +992,7 @@ for FilterMapIterator<'self, A, B, T> { /// An iterator which yields the current count and the element during iteration // FIXME #6967: Dummy A parameter to get around type inference bug +#[deriving(Clone)] pub struct EnumerateIterator { priv iter: T, priv count: uint @@ -1037,6 +1091,7 @@ impl<'self, A, T: Iterator> Iterator for TakeWhileIterator<'self, A, T> { /// An iterator which skips over `n` elements of `iter`. // FIXME #6967: Dummy A parameter to get around type inference bug +#[deriving(Clone)] pub struct SkipIterator { priv iter: T, priv n: uint @@ -1085,6 +1140,7 @@ impl> Iterator for SkipIterator { /// An iterator which only iterates over the first `n` iterations of `iter`. // FIXME #6967: Dummy A parameter to get around type inference bug +#[deriving(Clone)] pub struct TakeIterator { priv iter: T, priv n: uint @@ -1236,6 +1292,7 @@ impl<'self, A, St> Iterator for UnfoldrIterator<'self, A, St> { /// An infinite iterator starting at `start` and advancing by `step` with each /// iteration +#[deriving(Clone)] pub struct Counter { /// The current state the counter is at (next value to be yielded) state: A, @@ -1437,6 +1494,20 @@ mod tests { assert_eq!(i, 10); } + #[test] + fn test_cycle() { + let cycle_len = 3; + let it = Counter::new(0u,1).take_(cycle_len).cycle(); + assert_eq!(it.size_hint(), (uint::max_value, None)); + for it.take_(100).enumerate().advance |(i, x)| { + assert_eq!(i % cycle_len, x); + } + + let mut it = Counter::new(0u,1).take_(0).cycle(); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); + } + #[test] fn test_iterator_nth() { let v = &[0, 1, 2, 3, 4]; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 0811dab407e..c74c1e18e6d 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -288,6 +288,7 @@ impl<'self, C: CharEq> CharEq for &'self [C] { /// An iterator over the substrings of a string, separated by `sep`. +#[deriving(Clone)] pub struct StrCharSplitIterator<'self,Sep> { priv string: &'self str, priv position: uint, @@ -355,6 +356,7 @@ impl<'self, Sep: CharEq> Iterator<&'self str> for StrCharSplitIterator<'self, Se /// An iterator over the start and end indicies of the matches of a /// substring within a larger string +#[deriving(Clone)] pub struct StrMatchesIndexIterator<'self> { priv haystack: &'self str, priv needle: &'self str, @@ -363,6 +365,7 @@ pub struct StrMatchesIndexIterator<'self> { /// An iterator over the substrings of a string separated by a given /// search string +#[deriving(Clone)] pub struct StrStrSplitIterator<'self> { priv it: StrMatchesIndexIterator<'self>, priv last_end: uint, @@ -2269,6 +2272,7 @@ impl Clone for @str { /// External iterator for a string's characters. Use with the `std::iterator` /// module. +#[deriving(Clone)] pub struct StrCharIterator<'self> { priv index: uint, priv string: &'self str, @@ -2288,6 +2292,7 @@ impl<'self> Iterator for StrCharIterator<'self> { } /// External iterator for a string's characters in reverse order. Use /// with the `std::iterator` module. +#[deriving(Clone)] pub struct StrCharRevIterator<'self> { priv index: uint, priv string: &'self str, @@ -2308,6 +2313,7 @@ impl<'self> Iterator for StrCharRevIterator<'self> { /// External iterator for a string's bytes. Use with the `std::iterator` /// module. +#[deriving(Clone)] pub struct StrBytesIterator<'self> { priv it: vec::VecIterator<'self, u8> } @@ -2321,6 +2327,7 @@ impl<'self> Iterator for StrBytesIterator<'self> { /// External iterator for a string's bytes in reverse order. Use with /// the `std::iterator` module. +#[deriving(Clone)] pub struct StrBytesRevIterator<'self> { priv it: vec::VecRevIterator<'self, u8> } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 03e94a902c1..877ee65b4d6 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -2232,6 +2232,10 @@ iterator!{impl VecIterator -> &'self T} double_ended_iterator!{impl VecIterator -> &'self T} pub type VecRevIterator<'self, T> = InvertIterator<&'self T, VecIterator<'self, T>>; +impl<'self, T> Clone for VecIterator<'self, T> { + fn clone(&self) -> VecIterator<'self, T> { *self } +} + //iterator!{struct VecMutIterator -> *mut T, &'self mut T} /// An iterator for mutating the elements of a vector. pub struct VecMutIterator<'self, T> { @@ -2244,6 +2248,7 @@ double_ended_iterator!{impl VecMutIterator -> &'self mut T} pub type VecMutRevIterator<'self, T> = InvertIterator<&'self mut T, VecMutIterator<'self, T>>; /// An iterator that moves out of a vector. +#[deriving(Clone)] pub struct VecConsumeIterator { priv v: ~[T], priv idx: uint, @@ -2270,6 +2275,7 @@ impl Iterator for VecConsumeIterator { } /// An iterator that moves out of a vector in reverse order. +#[deriving(Clone)] pub struct VecConsumeRevIterator { priv v: ~[T] } @@ -3185,6 +3191,17 @@ mod tests { assert_eq!(xs.mut_rev_iter().size_hint(), (5, Some(5))); } + #[test] + fn test_iter_clone() { + let xs = [1, 2, 5]; + let mut it = xs.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next(), jt.next()); + } + #[test] fn test_mut_iterator() { use iterator::*;