about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/core/src/slice/iter/macros.rs15
-rw-r--r--library/core/tests/slice.rs42
2 files changed, 57 insertions, 0 deletions
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index 457b2a3605e..791a88dd97f 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -185,6 +185,13 @@ macro_rules! iterator {
                 }
             }
 
+            fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+                let advance = cmp::min(n, len!(self));
+                // SAFETY: By construction, `advance` does not exceed `self.len()`.
+                unsafe { self.post_inc_start(advance as isize) };
+                if advance == n { Ok(()) } else { Err(advance) }
+            }
+
             #[inline]
             fn last(mut self) -> Option<$elem> {
                 self.next_back()
@@ -371,6 +378,14 @@ macro_rules! iterator {
                     Some(next_back_unchecked!(self))
                 }
             }
+
+            #[inline]
+            fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+                let advance = cmp::min(n, len!(self));
+                // SAFETY: By construction, `advance` does not exceed `self.len()`.
+                unsafe { self.pre_dec_end(advance as isize) };
+                if advance == n { Ok(()) } else { Err(advance) }
+            }
         }
 
         #[stable(feature = "fused", since = "1.26.0")]
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 3a98cd9d2ee..240b894057c 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -135,6 +135,48 @@ fn test_partition_point() {
 }
 
 #[test]
+fn test_iterator_advance_by() {
+    let v = &[0, 1, 2, 3, 4];
+
+    for i in 0..=v.len() {
+        let mut iter = v.iter();
+        iter.advance_by(i).unwrap();
+        assert_eq!(iter.as_slice(), &v[i..]);
+    }
+
+    let mut iter = v.iter();
+    assert_eq!(iter.advance_by(v.len() + 1), Err(v.len()));
+    assert_eq!(iter.as_slice(), &[]);
+
+    let mut iter = v.iter();
+    iter.advance_by(3).unwrap();
+    assert_eq!(iter.as_slice(), &v[3..]);
+    iter.advance_by(2).unwrap();
+    assert_eq!(iter.as_slice(), &[]);
+}
+
+#[test]
+fn test_iterator_advance_back_by() {
+    let v = &[0, 1, 2, 3, 4];
+
+    for i in 0..=v.len() {
+        let mut iter = v.iter();
+        iter.advance_back_by(i).unwrap();
+        assert_eq!(iter.as_slice(), &v[..v.len() - i]);
+    }
+
+    let mut iter = v.iter();
+    assert_eq!(iter.advance_back_by(v.len() + 1), Err(v.len()));
+    assert_eq!(iter.as_slice(), &[]);
+
+    let mut iter = v.iter();
+    iter.advance_back_by(3).unwrap();
+    assert_eq!(iter.as_slice(), &v[..v.len() - 3]);
+    iter.advance_back_by(2).unwrap();
+    assert_eq!(iter.as_slice(), &[]);
+}
+
+#[test]
 fn test_iterator_nth() {
     let v: &[_] = &[0, 1, 2, 3, 4];
     for i in 0..v.len() {