From 26d4c8f01c07fdb3b0c0354dd9b509c955a87e9c Mon Sep 17 00:00:00 2001 From: Adrian Friedli Date: Sat, 8 Jun 2019 22:30:45 +0200 Subject: [PATCH 1/2] implement nth_back for Range --- src/libcore/iter/range.rs | 13 +++++++++++++ src/libcore/tests/iter.rs | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 6bbf776fb8f17..e171108a146a6 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -281,6 +281,19 @@ impl DoubleEndedIterator for ops::Range { None } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + if let Some(minus_n) = self.end.sub_usize(n) { + if minus_n > self.start { + self.end = minus_n.sub_one(); + return Some(self.end.clone()) + } + } + + self.end = self.start.clone(); + None + } } #[stable(feature = "fused", since = "1.26.0")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index bedb9e756129c..171a33695bc6a 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1657,6 +1657,23 @@ fn test_range_nth() { assert_eq!(r, 20..20); } +#[test] +fn test_range_nth_back() { + assert_eq!((10..15).nth_back(0), Some(14)); + assert_eq!((10..15).nth_back(1), Some(13)); + assert_eq!((10..15).nth_back(4), Some(10)); + assert_eq!((10..15).nth_back(5), None); + assert_eq!((-120..80_i8).nth_back(199), Some(-120)); + + let mut r = 10..20; + assert_eq!(r.nth_back(2), Some(17)); + assert_eq!(r, 10..17); + assert_eq!(r.nth_back(2), Some(14)); + assert_eq!(r, 10..14); + assert_eq!(r.nth_back(10), None); + assert_eq!(r, 10..10); +} + #[test] fn test_range_from_nth() { assert_eq!((10..).nth(0), Some(10)); From 8590074a01364c2263f6e3c3c42e4137e2f77b65 Mon Sep 17 00:00:00 2001 From: Adrian Friedli Date: Sun, 9 Jun 2019 22:45:11 +0200 Subject: [PATCH 2/2] implement nth_back for RangeInclusive --- src/libcore/iter/range.rs | 28 ++++++++++++++++++++++++++++ src/libcore/tests/iter.rs | 20 ++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index e171108a146a6..efda3b263cc97 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -451,6 +451,34 @@ impl DoubleEndedIterator for ops::RangeInclusive { }) } + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.compute_is_empty(); + if self.is_empty.unwrap_or_default() { + return None; + } + + if let Some(minus_n) = self.end.sub_usize(n) { + use crate::cmp::Ordering::*; + + match minus_n.partial_cmp(&self.start) { + Some(Greater) => { + self.is_empty = Some(false); + self.end = minus_n.sub_one(); + return Some(minus_n); + } + Some(Equal) => { + self.is_empty = Some(true); + return Some(minus_n); + } + _ => {} + } + } + + self.is_empty = Some(true); + None + } + #[inline] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 171a33695bc6a..020618ae7aeed 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1731,6 +1731,26 @@ fn test_range_inclusive_nth() { assert_eq!(ExactSizeIterator::is_empty(&r), true); } +#[test] +fn test_range_inclusive_nth_back() { + assert_eq!((10..=15).nth_back(0), Some(15)); + assert_eq!((10..=15).nth_back(1), Some(14)); + assert_eq!((10..=15).nth_back(5), Some(10)); + assert_eq!((10..=15).nth_back(6), None); + assert_eq!((-120..=80_i8).nth_back(200), Some(-120)); + + let mut r = 10_u8..=20; + assert_eq!(r.nth_back(2), Some(18)); + assert_eq!(r, 10..=17); + assert_eq!(r.nth_back(2), Some(15)); + assert_eq!(r, 10..=14); + assert_eq!(r.is_empty(), false); + assert_eq!(ExactSizeIterator::is_empty(&r), false); + assert_eq!(r.nth_back(10), None); + assert_eq!(r.is_empty(), true); + assert_eq!(ExactSizeIterator::is_empty(&r), true); +} + #[test] fn test_range_step() { #![allow(deprecated)]