about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/doc/unstable-book/src/library-features/iterator-step-by.md7
-rw-r--r--src/libcore/iter/iterator.rs35
-rw-r--r--src/libcore/iter/mod.rs37
-rw-r--r--src/libcore/tests/iter.rs29
-rw-r--r--src/libcore/tests/lib.rs1
5 files changed, 106 insertions, 3 deletions
diff --git a/src/doc/unstable-book/src/library-features/iterator-step-by.md b/src/doc/unstable-book/src/library-features/iterator-step-by.md
new file mode 100644
index 00000000000..8467cb68862
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/iterator-step-by.md
@@ -0,0 +1,7 @@
+# `iterator_step_by`
+
+The tracking issue for this feature is: [#27741]
+
+[#27741]: https://github.com/rust-lang/rust/issues/27741
+
+------------------------
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 67b97afb976..77cbdb98c83 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -11,7 +11,7 @@
 use cmp::Ordering;
 
 use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse};
-use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile, Rev};
+use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev};
 use super::{Zip, Sum, Product};
 use super::{ChainState, FromIterator, ZipImpl};
 
@@ -258,6 +258,39 @@ pub trait Iterator {
         None
     }
 
+    /// Creates an iterator starting at the same point, but stepping by
+    /// the given amount at each iteration.
+    ///
+    /// Note that it will always return the first element of the range,
+    /// regardless of the step given.
+    ///
+    /// # Panics
+    ///
+    /// The method will panic if the given step is `0`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iterator_step_by)]
+    /// let a = [0, 1, 2, 3, 4, 5];
+    /// let mut iter = a.into_iter().step_by(2);
+    ///
+    /// assert_eq!(iter.next(), Some(&0));
+    /// assert_eq!(iter.next(), Some(&2));
+    /// assert_eq!(iter.next(), Some(&4));
+    /// assert_eq!(iter.next(), None);
+    /// ```
+    #[inline]
+    #[unstable(feature = "iterator_step_by",
+               reason = "unstable replacement of Range::step_by",
+               issue = "27741")]
+    fn step_by(self, step: usize) -> StepBy<Self> where Self: Sized {
+        assert!(step != 0);
+        StepBy{iter: self, step: step - 1, first_take: true}
+    }
+
     /// Takes two iterators and creates a new iterator over both in sequence.
     ///
     /// `chain()` will return a new iterator which will first iterate over
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 273f9d0e6f6..420ff0f7119 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -313,7 +313,7 @@ pub use self::iterator::Iterator;
 pub use self::range::Step;
 #[unstable(feature = "step_by", reason = "recent addition",
            issue = "27741")]
-pub use self::range::StepBy;
+pub use self::range::StepBy as DeprecatedStepBy;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::sources::{Repeat, repeat};
@@ -520,6 +520,41 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
 #[unstable(feature = "fused", issue = "35602")]
 impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
 
+/// An iterator that steps by n elements every iteration.
+///
+/// This `struct` is created by the [`step_by`] method on [`Iterator`]. See
+/// its documentation for more.
+///
+/// [`step_by`]: trait.Iterator.html#method.step_by
+/// [`Iterator`]: trait.Iterator.html
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[unstable(feature = "iterator_step_by",
+           reason = "unstable replacement of Range::step_by",
+           issue = "27741")]
+#[derive(Clone, Debug)]
+pub struct StepBy<I> {
+    iter: I,
+    step: usize,
+    first_take: bool,
+}
+
+#[unstable(feature = "iterator_step_by",
+           reason = "unstable replacement of Range::step_by",
+           issue = "27741")]
+impl<I> Iterator for StepBy<I> where I: Iterator {
+    type Item = I::Item;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.first_take {
+            self.first_take = false;
+            self.iter.next()
+        } else {
+            self.iter.nth(self.step)
+        }
+    }
+}
+
 /// An iterator that strings two iterators together.
 ///
 /// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 001fa304cd0..ad91ba9be58 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -145,6 +145,33 @@ fn test_iterator_chain_find() {
 }
 
 #[test]
+fn test_iterator_step_by() {
+    // Identity
+    // Replace with (0..).step_by(1) after Range::step_by gets removed
+    let mut it = Iterator::step_by((0..), 1).take(3);
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.next(), Some(1));
+    assert_eq!(it.next(), Some(2));
+    assert_eq!(it.next(), None);
+
+    // Replace with (0..).step_by(3) after Range::step_by gets removed
+    let mut it = Iterator::step_by((0..), 3).take(4);
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.next(), Some(3));
+    assert_eq!(it.next(), Some(6));
+    assert_eq!(it.next(), Some(9));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+#[should_panic]
+fn test_iterator_step_by_zero() {
+    // Replace with (0..).step_by(0) after Range::step_by gets removed
+    let mut it = Iterator::step_by((0..), 0);
+    it.next();
+}
+
+#[test]
 fn test_filter_map() {
     let it = (0..).step_by(1).take(10)
         .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
@@ -1119,4 +1146,4 @@ fn test_step_replace_no_between() {
     let y = x.replace_one();
     assert_eq!(x, 1);
     assert_eq!(y, 5);
-}
\ No newline at end of file
+}
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index f0c46a6f194..c52155ead4f 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -20,6 +20,7 @@
 #![feature(fixed_size_array)]
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
+#![feature(iterator_step_by)]
 #![feature(i128_type)]
 #![feature(iter_rfind)]
 #![feature(libc)]