rust-lang/rust · #165132

Implement `advance_back_by` on `Fuse`

maxdexh · merged Oct 31, 20262 files · 108 + / 5 −
library/core/src/iter/adapters/fuse.rs41 + / 0 −
@@ -138,6 +138,11 @@ where         FuseImpl::next_back(self)     } +    #[inline]+    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {+        FuseImpl::advance_back_by(self, n)+    }+     #[inline]     fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {         FuseImpl::nth_back(self, n)@@ -277,6 +282,9 @@ trait FuseImpl<I> {      // Functions specific to DoubleEndedIterators     fn next_back(&mut self) -> Option<Self::Item>+    where+        I: DoubleEndedIterator;+    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>>     where         I: DoubleEndedIterator;     fn nth_back(&mut self, n: usize) -> Option<Self::Item>@@ -358,6 +366,25 @@ where         and_then_or_clear(&mut self.iter, |iter| iter.next_back())     } +    #[inline]+    default fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>>+    where+        I: DoubleEndedIterator,+    {+        let Some(iter) = &mut self.iter else {+            return match NonZero::new(n) {+                Some(n) => Err(n),+                None => Ok(()),+            };+        };++        let res = iter.advance_back_by(n);+        if res.is_err() {+            self.iter = None;+        }+        res+    }+     #[inline]     default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>     where@@ -448,6 +475,20 @@ where         self.iter.as_mut()?.next_back()     } +    #[inline]+    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>>+    where+        I: DoubleEndedIterator,+    {+        match &mut self.iter {+            Some(iter) => iter.advance_back_by(n),+            None => match NonZero::new(n) {+                Some(n) => Err(n),+                None => Ok(()),+            },+        }+    }+     #[inline]     fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>     where
library/coretests/tests/iter/adapters/fuse.rs67 + / 5 −
@@ -1,9 +1,9 @@ use core::iter::*;  #[test]-fn test_fuse_nth() {+fn test_fuse_fused_nth() {     let xs = [0, 1, 2];-    let mut it = xs.iter();+    let mut it = xs.iter().fuse();      assert_eq!(it.len(), 3);     assert_eq!(it.nth(2), Some(&2));@@ -12,10 +12,72 @@ fn test_fuse_nth() {     assert_eq!(it.len(), 0); } +#[test]+fn test_fuse_fused_nth_back() {+    let xs = [0, 1, 2];+    let mut it = xs.iter().fuse();++    assert_eq!(it.len(), 3);+    assert_eq!(it.nth_back(2), Some(&0));+    assert_eq!(it.len(), 0);+    assert_eq!(it.nth_back(2), None);+    assert_eq!(it.len(), 0);+}++#[test]+fn test_fuse_fused_advance() {+    let xs = [0, 1, 2, 3];+    let mut it = xs.iter().fuse();++    assert_eq!(it.len(), 4);+    assert_eq!(it.advance_by(2), Ok(()));+    assert_eq!(it.next(), Some(&2));+    assert_eq!(it.len(), 1);+    assert_eq!(it.advance_by(2).map_err(|it| it.get()), Err(1));+    assert_eq!(it.next(), None);+    assert_eq!(it.len(), 0);+}++#[test]+fn test_fuse_fused_advance_back() {+    let xs = [0, 1, 2, 3];+    let mut it = xs.iter().fuse();++    assert_eq!(it.len(), 4);+    assert_eq!(it.advance_back_by(2), Ok(()));+    assert_eq!(it.next_back(), Some(&1));+    assert_eq!(it.len(), 1);+    assert_eq!(it.advance_back_by(2).map_err(|it| it.get()), Err(1));+    assert_eq!(it.next(), None);+    assert_eq!(it.len(), 0);+}++#[test]+fn test_fuse_unfused_nth() {+    let mut xs = [0, 1, 2].into_iter().map(Some).chain([None]).chain([3, 4, 5].map(Some));+    let mut it = core::iter::from_fn(|| xs.next().flatten()).fuse();++    assert_eq!(it.nth(1), Some(1));+    assert_eq!(it.nth(1), None);+    assert_eq!(xs.next(), Some(Some(3)));+}++#[test]+fn test_fuse_unfused_advance() {+    let mut xs = [0, 1, 2].into_iter().map(Some).chain([None]).chain([3, 4, 5].map(Some));+    let mut it = core::iter::from_fn(|| xs.next().flatten()).fuse();++    assert_eq!(it.advance_by(1), Ok(()));+    assert_eq!(it.next(), Some(1));+    assert_eq!(it.advance_by(2).map_err(|it| it.get()), Err(1));+    assert_eq!(it.next(), None);+    assert_eq!(xs.next(), Some(Some(3)));+}+ #[test] fn test_fuse_last() {     let xs = [0, 1, 2];-    let it = xs.iter();+    let it = xs.iter().fuse();      assert_eq!(it.len(), 3);     assert_eq!(it.last(), Some(&2));@@ -24,7 +86,7 @@ fn test_fuse_last() { #[test] fn test_fuse_count() {     let xs = [0, 1, 2];-    let it = xs.iter();+    let it = xs.iter().fuse();      assert_eq!(it.len(), 3);     assert_eq!(it.count(), 3);@@ -58,7 +120,7 @@ fn test_fuse_fold() {  #[test] fn test_fuse() {-    let mut it = 0..3;+    let mut it = (0..3).fuse();     assert_eq!(it.len(), 3);     assert_eq!(it.next(), Some(0));     assert_eq!(it.len(), 2);