diff --git a/src/iter_index.rs b/src/iter_index.rs index 679a88075..cf3222c9d 100644 --- a/src/iter_index.rs +++ b/src/iter_index.rs @@ -48,11 +48,17 @@ impl IteratorIndex for RangeInclusive where I: Iterator, { - type Output = Skip>; + type Output = Take>; fn index(self, iter: I) -> Self::Output { - assert_ne!(*self.end(), usize::MAX); - iter.take(self.end() + 1).skip(*self.start()) + // end - start + 1 without overflowing if possible + let length = if *self.end() == usize::MAX { + assert_ne!(*self.start(), 0); + self.end() - self.start() + 1 + } else { + (self.end() + 1).saturating_sub(*self.start()) + }; + iter.skip(*self.start()).take(length) } } diff --git a/src/lib.rs b/src/lib.rs index 29b55f550..786c0cc4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -511,7 +511,7 @@ pub trait Itertools: Iterator { /// /// Works similarly to [`slice::get`](https://doc.rust-lang.org/std/primitive.slice.html#method.get). /// - /// **Panics** if the range includes `usize::MAX`. + /// **Panics** for ranges `..=usize::MAX` and `0..=usize::MAX`. /// /// It's a generalisation of [`Iterator::take`] and [`Iterator::skip`], /// and uses these under the hood. diff --git a/tests/test_core.rs b/tests/test_core.rs index 6f7dc1fda..32af246c0 100644 --- a/tests/test_core.rs +++ b/tests/test_core.rs @@ -40,6 +40,19 @@ fn get_dei_esi_then_dei_esi( is_dei_esi(it.get(..)); } +#[test] +fn get_1_max() { + let mut it = (0..5).get(1..=usize::MAX); + assert_eq!(it.next(), Some(1)); + assert_eq!(it.next_back(), Some(4)); +} + +#[test] +#[should_panic] +fn get_full_range_inclusive() { + let _it = (0..5).get(0..=usize::MAX); +} + #[test] fn product0() { let mut prod = iproduct!();