about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKonrad Borowski <konrad@borowski.pw>2018-12-05 14:39:42 +0100
committerKonrad Borowski <konrad@borowski.pw>2018-12-05 15:40:14 +0100
commitab2cd6070e73dc79a5b5e0b67cad120f0ccb4217 (patch)
tree0ba4c6db9c99a6aa6fbc1f820fad8febbb15db9f
parent705383adb037dddd834970d2c10edb32dae9fa56 (diff)
downloadrust-ab2cd6070e73dc79a5b5e0b67cad120f0ccb4217.tar.gz
rust-ab2cd6070e73dc79a5b5e0b67cad120f0ccb4217.zip
Add unstable Iterator::copied()
-rw-r--r--src/libcore/iter/iterator.rs31
-rw-r--r--src/libcore/iter/mod.rs98
2 files changed, 128 insertions, 1 deletions
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 3063cb1a7df..80bd5698c47 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -12,7 +12,7 @@ use cmp::Ordering;
 use ops::Try;
 
 use super::LoopState;
-use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, Fuse};
+use super::{Chain, Cycle, Copied, Cloned, Enumerate, Filter, FilterMap, Fuse};
 use super::{Flatten, FlatMap, flatten_compat};
 use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev};
 use super::{Zip, Sum, Product};
@@ -2234,6 +2234,35 @@ pub trait Iterator {
         (ts, us)
     }
 
+    /// Creates an iterator which copies all of its elements.
+    ///
+    /// This is useful when you have an iterator over `&T`, but you need an
+    /// iterator over `T`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iter_copied)]
+    ///
+    /// let a = [1, 2, 3];
+    ///
+    /// let v_cloned: Vec<_> = a.iter().copied().collect();
+    ///
+    /// // copied is the same as .map(|&x| x)
+    /// let v_map: Vec<_> = a.iter().map(|&x| x).collect();
+    ///
+    /// assert_eq!(v_cloned, vec![1, 2, 3]);
+    /// assert_eq!(v_map, vec![1, 2, 3]);
+    /// ```
+    #[unstable(feature = "iter_copied", issue = "0")]
+    fn copied<'a, T: 'a>(self) -> Copied<Self>
+        where Self: Sized + Iterator<Item=&'a T>, T: Copy
+    {
+        Copied { it: self }
+    }
+
     /// Creates an iterator which [`clone`]s all of its elements.
     ///
     /// This is useful when you have an iterator over `&T`, but you need an
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 62e1f9fcb64..a23a404e378 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -501,6 +501,104 @@ impl<I> FusedIterator for Rev<I>
 unsafe impl<I> TrustedLen for Rev<I>
     where I: TrustedLen + DoubleEndedIterator {}
 
+/// An iterator that copies the elements of an underlying iterator.
+///
+/// This `struct` is created by the [`copied`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`copied`]: trait.Iterator.html#method.copied
+/// [`Iterator`]: trait.Iterator.html
+#[unstable(feature = "iter_copied", issue = "0")]
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[derive(Clone, Debug)]
+pub struct Copied<I> {
+    it: I,
+}
+
+#[unstable(feature = "iter_copied", issue = "0")]
+impl<'a, I, T: 'a> Iterator for Copied<I>
+    where I: Iterator<Item=&'a T>, T: Copy
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        self.it.next().copied()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.it.size_hint()
+    }
+
+    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
+        Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
+    {
+        self.it.try_fold(init, move |acc, &elt| f(acc, elt))
+    }
+
+    fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
+        where F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.it.fold(init, move |acc, &elt| f(acc, elt))
+    }
+}
+
+#[unstable(feature = "iter_copied", issue = "0")]
+impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
+    where I: DoubleEndedIterator<Item=&'a T>, T: Copy
+{
+    fn next_back(&mut self) -> Option<T> {
+        self.it.next_back().cloned()
+    }
+
+    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
+        Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
+    {
+        self.it.try_rfold(init, move |acc, elt| f(acc, elt.clone()))
+    }
+
+    fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc
+        where F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.it.rfold(init, move |acc, elt| f(acc, elt.clone()))
+    }
+}
+
+#[unstable(feature = "iter_copied", issue = "0")]
+impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
+    where I: ExactSizeIterator<Item=&'a T>, T: Copy
+{
+    fn len(&self) -> usize {
+        self.it.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.it.is_empty()
+    }
+}
+
+#[unstable(feature = "iter_copied", issue = "0")]
+impl<'a, I, T: 'a> FusedIterator for Copied<I>
+    where I: FusedIterator<Item=&'a T>, T: Copy
+{}
+
+#[doc(hidden)]
+unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Copied<I>
+    where I: TrustedRandomAccess<Item=&'a T>, T: Copy
+{
+    unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
+        *self.it.get_unchecked(i)
+    }
+
+    #[inline]
+    fn may_have_side_effect() -> bool { false }
+}
+
+#[unstable(feature = "iter_copied", issue = "0")]
+unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
+    where I: TrustedLen<Item=&'a T>,
+          T: Copy
+{}
+
 /// An iterator that clones the elements of an underlying iterator.
 ///
 /// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its