From 5c7f0cdd12fec684aceaca0278769bc01cd452d2 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Tue, 25 Jul 2023 23:11:49 -0500 Subject: [PATCH 1/3] Add `peek_mut` and `peek_nth_mut` to `PeekNth` which mirror `std::iter::Peekable::peek_mut`. --- src/peek_nth.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/peek_nth.rs b/src/peek_nth.rs index bcca45838..9dddb8f01 100644 --- a/src/peek_nth.rs +++ b/src/peek_nth.rs @@ -39,6 +39,11 @@ where self.peek_nth(0) } + /// Works exactly like the `peek_mut` method in `std::iter::Peekable` + pub fn peek_mut(&mut self) -> Option<&mut I::Item> { + self.peek_nth_mut(0) + } + /// Returns a reference to the `nth` value without advancing the iterator. /// /// # Examples @@ -69,6 +74,47 @@ where self.buf.get(n) } + + /// Returns a mutable reference to the `nth` value without advancing the iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use itertools::peek_nth; + /// + /// let xs = vec![1, 2, 3, 4, 5]; + /// let mut iter = peek_nth(xs.into_iter()); + /// + /// assert_eq!(iter.peek_nth_mut(0), Some(&mut 1)); + /// assert_eq!(iter.next(), Some(1)); + /// + /// // The iterator does not advance even if we call `peek_nth_mut` multiple times + /// assert_eq!(iter.peek_nth_mut(0), Some(&mut 2)); + /// assert_eq!(iter.peek_nth_mut(1), Some(&mut 3)); + /// assert_eq!(iter.next(), Some(2)); + /// + /// // Peek into the iterator and set the value behind the mutable reference. + /// if let Some(p) = iter.peek_nth_mut(1) { + /// assert_eq!(*p, 4); + /// *p = 9; + /// } + /// + /// // The value we put in reappears as the iterator continues. + /// assert_eq!(iter.next(), Some(3)); + /// assert_eq!(iter.next(), Some(9)); + /// + /// // Calling `peek_nth_mut` past the end of the iterator will return `None` + /// assert_eq!(iter.peek_nth_mut(1), None); + /// ``` + pub fn peek_nth_mut(&mut self, n: usize) -> Option<&mut I::Item> { + let unbuffered_items = (n + 1).saturating_sub(self.buf.len()); + + self.buf.extend(self.iter.by_ref().take(unbuffered_items)); + + self.buf.get_mut(n) + } } impl Iterator for PeekNth From 554ee73b8be3634461a3e40cf442ab1b7c2bbf50 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 26 Jul 2023 00:17:34 -0500 Subject: [PATCH 2/3] Add quickcheck tests for PeekNth. --- tests/quick.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/quick.rs b/tests/quick.rs index 267640fe4..0d7cd9307 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -758,6 +758,32 @@ quickcheck! { } } +quickcheck! { + fn correct_peek_nth(mut a: Vec) -> () { + let mut it = peek_nth(a.clone()); + for start_pos in 0..a.len() + 2 { + for real_idx in start_pos..a.len() + 2 { + let peek_idx = real_idx - start_pos; + assert_eq!(it.peek_nth(peek_idx), a.get(real_idx)); + assert_eq!(it.peek_nth_mut(peek_idx), a.get_mut(real_idx)); + } + assert_eq!(it.next(), a.get(start_pos).copied()); + } + } + + fn peek_nth_mut_replace(a: Vec, b: Vec) -> () { + let mut it = peek_nth(a.iter()); + for i in 0..a.len().min(b.len()) { + *it.peek_nth_mut(i).unwrap() = &b[i]; + } + for i in 0..a.len() { + assert_eq!(it.next().unwrap(), b.get(i).unwrap_or(&a[i])); + } + assert_eq!(it.next(), None); + assert_eq!(it.next(), None); + } +} + quickcheck! { fn dedup_via_coalesce(a: Vec) -> bool { let mut b = a.clone(); From 7748ee4453d9cfa01029b33efb86b430453b3003 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Mon, 9 Oct 2023 12:59:04 +0200 Subject: [PATCH 3/3] Update `PeekNth::peek_nth` doctest Use `into_iter` instead to avoid `&&`. I did the same in `PeekNth::peek_nth_mut` to avoid `&mut &`. --- src/peek_nth.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/peek_nth.rs b/src/peek_nth.rs index 9dddb8f01..1ae428ba0 100644 --- a/src/peek_nth.rs +++ b/src/peek_nth.rs @@ -50,19 +50,19 @@ where /// /// Basic usage: /// - /// ```rust + /// ``` /// use itertools::peek_nth; /// - /// let xs = vec![1,2,3]; - /// let mut iter = peek_nth(xs.iter()); + /// let xs = vec![1, 2, 3]; + /// let mut iter = peek_nth(xs.into_iter()); /// - /// assert_eq!(iter.peek_nth(0), Some(&&1)); - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.peek_nth(0), Some(&1)); + /// assert_eq!(iter.next(), Some(1)); /// /// // The iterator does not advance even if we call `peek_nth` multiple times - /// assert_eq!(iter.peek_nth(0), Some(&&2)); - /// assert_eq!(iter.peek_nth(1), Some(&&3)); - /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.peek_nth(0), Some(&2)); + /// assert_eq!(iter.peek_nth(1), Some(&3)); + /// assert_eq!(iter.next(), Some(2)); /// /// // Calling `peek_nth` past the end of the iterator will return `None` /// assert_eq!(iter.peek_nth(1), None);