diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 93d8d7d6e48a9..3b62c8da1ebe1 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -65,9 +65,10 @@ use cmp; use cmp::Ord; use mem; use num::{ToPrimitive, Int}; -use ops::Add; +use ops::{Add, Deref}; use option::{Option, Some, None}; use uint; + #[deprecated = "renamed to Extend"] pub use self::Extend as Extendable; /// Conversion from an `Iterator` @@ -1021,6 +1022,44 @@ impl MinMaxResult { } } +/// A trait for iterators that contain cloneable elements +pub trait CloneIteratorExt { + /// Creates an iterator that clones the elements it yields. Useful for converting an + /// Iterator<&T> to an Iterator. + fn cloned(self) -> Cloned; +} + + +impl, I: Iterator> CloneIteratorExt for I { + fn cloned(self) -> Cloned { + Cloned { it: self } + } +} + +/// An iterator that clones the elements of an underlying iterator +pub struct Cloned { + it: I, +} + +impl, I: Iterator> Iterator for Cloned { + fn next(&mut self) -> Option { + self.it.next().cloned() + } + + fn size_hint(&self) -> (uint, Option) { + self.it.size_hint() + } +} + +impl, I: DoubleEndedIterator> + DoubleEndedIterator for Cloned { + fn next_back(&mut self) -> Option { + self.it.next_back().cloned() + } +} + +impl, I: ExactSize> ExactSize for Cloned {} + /// A trait for iterators that are cloneable. pub trait CloneableIterator { /// Repeats an iterator endlessly diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 32aff498ba109..d046faa82d405 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -440,6 +440,23 @@ fn test_rev() { vec![16, 14, 12, 10, 8, 6]); } +#[test] +fn test_cloned() { + let xs = [2u8, 4, 6, 8]; + + let mut it = xs.iter().cloned(); + assert_eq!(it.len(), 4); + assert_eq!(it.next(), Some(2)); + assert_eq!(it.len(), 3); + assert_eq!(it.next(), Some(4)); + assert_eq!(it.len(), 2); + assert_eq!(it.next_back(), Some(8)); + assert_eq!(it.len(), 1); + assert_eq!(it.next_back(), Some(6)); + assert_eq!(it.len(), 0); + assert_eq!(it.next_back(), None); +} + #[test] fn test_double_ended_map() { let xs = [1i, 2, 3, 4, 5, 6];