From 7ab9accee6ff33abfba6ee43e0df60c8ed595268 Mon Sep 17 00:00:00 2001 From: matt rice Date: Sat, 25 Nov 2023 11:04:21 -0800 Subject: [PATCH] add `lend_refs` and `lend_refs_mut` These both take a `Iterator` and subsequently lend references, and mut references respectively to the iterator's item. --- src/to_lending/lend_refs.rs | 55 ++++++++++++++++++++++++++++++ src/to_lending/lend_refs_mut.rs | 56 +++++++++++++++++++++++++++++++ src/to_lending/mod.rs | 4 +++ src/traits/to_lending_iterator.rs | 20 ++++++++++- 4 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/to_lending/lend_refs.rs create mode 100644 src/to_lending/lend_refs_mut.rs diff --git a/src/to_lending/lend_refs.rs b/src/to_lending/lend_refs.rs new file mode 100644 index 0000000..53eb116 --- /dev/null +++ b/src/to_lending/lend_refs.rs @@ -0,0 +1,55 @@ +use crate::LendingIterator; + +/// A lending iterator that given an iterator, lends +/// references to the given iterator's items. +pub struct LendRefs { + item: Option, + iter: I, +} + +impl LendRefs { + pub(crate) fn new(iter: I) -> LendRefs { + LendRefs { item: None, iter } + } +} + +impl LendingIterator for LendRefs +where + I: Iterator, +{ + type Item<'a> = &'a I::Item where Self: 'a; + + fn next(&mut self) -> Option> { + self.item = self.iter.next(); + self.item.as_ref() + } +} +#[cfg(test)] +mod test { + use crate::{LendingIterator, ToLendingIterator}; + #[derive(Clone, Eq, PartialEq, Debug)] + struct Foo(usize); + struct W { + x: Foo, + } + impl LendingIterator for W { + type Item<'a> = &'a Foo where Self: 'a; + fn next(&mut self) -> Option> { + self.x.0 += 1; + Some(&self.x) + } + } + #[test] + fn test() { + let mut xs = Vec::new(); + test_helper().take(3).for_each(|x: &Foo| { + xs.push(x.clone()); + }); + assert_eq!(xs, vec![Foo(0), Foo(1), Foo(2)]); + } + + fn test_helper() -> impl for<'a> LendingIterator = &'a Foo> { + let w = W { x: Foo(0) }; + std::iter::once(Foo(0)).lend_refs().chain(w) + } +} diff --git a/src/to_lending/lend_refs_mut.rs b/src/to_lending/lend_refs_mut.rs new file mode 100644 index 0000000..e22bbca --- /dev/null +++ b/src/to_lending/lend_refs_mut.rs @@ -0,0 +1,56 @@ +use crate::LendingIterator; + +/// A lending iterator that given an iterator, lends +/// mutable references to the given iterator's items. +pub struct LendRefsMut { + item: Option, + iter: I, +} + +impl LendRefsMut { + pub(crate) fn new(iter: I) -> LendRefsMut { + LendRefsMut { item: None, iter } + } +} + +impl LendingIterator for LendRefsMut { + type Item<'a> = &'a mut I::Item where Self: 'a; + + fn next(&mut self) -> Option> { + self.item = self.iter.next(); + self.item.as_mut() + } +} + +#[cfg(test)] +mod test { + use crate::{LendingIterator, ToLendingIterator}; + #[derive(Clone, Eq, PartialEq, Debug)] + struct Foo(usize); + struct W { + x: Foo, + } + + impl LendingIterator for W { + type Item<'a> = &'a mut Foo where Self: 'a; + fn next(&mut self) -> Option> { + self.x.0 += 1; + Some(&mut self.x) + } + } + + #[test] + fn test() { + let mut xs = Vec::new(); + test_helper().take(3).for_each(|x: &mut Foo| { + x.0 += 2; + xs.push(x.clone()); + }); + assert_eq!(xs, vec![Foo(2), Foo(3), Foo(6)]); + } + + fn test_helper() -> impl for<'a> LendingIterator = &'a mut Foo> { + let w = W { x: Foo(0) }; + std::iter::once(Foo(0)).lend_refs_mut().chain(w) + } +} diff --git a/src/to_lending/mod.rs b/src/to_lending/mod.rs index 289f87f..86ffceb 100644 --- a/src/to_lending/mod.rs +++ b/src/to_lending/mod.rs @@ -1,6 +1,10 @@ mod into_lending; +mod lend_refs; +mod lend_refs_mut; mod windows; mod windows_mut; pub use self::into_lending::IntoLending; +pub use self::lend_refs::LendRefs; +pub use self::lend_refs_mut::LendRefsMut; pub use self::windows::Windows; pub use self::windows_mut::WindowsMut; diff --git a/src/traits/to_lending_iterator.rs b/src/traits/to_lending_iterator.rs index a7243e3..0147f83 100644 --- a/src/traits/to_lending_iterator.rs +++ b/src/traits/to_lending_iterator.rs @@ -1,4 +1,4 @@ -use crate::{IntoLending, Windows, WindowsMut}; +use crate::{IntoLending, LendRefs, LendRefsMut, Windows, WindowsMut}; /// An extension trait for iterators that allows turning them into lending iterators (over windows of elements). pub trait ToLendingIterator: IntoIterator { @@ -35,6 +35,24 @@ pub trait ToLendingIterator: IntoIterator { { IntoLending::new(self.into_iter()) } + + /// Turns this iterator into a lending iterator that lends references + /// to the iterator's items. + fn lend_refs(self) -> LendRefs + where + Self: Sized, + { + LendRefs::new(self.into_iter()) + } + + /// Turns this iterator into a lending iterator that lends mutable references + /// to the iterator's items. + fn lend_refs_mut(self) -> LendRefsMut + where + Self: Sized, + { + LendRefsMut::new(self.into_iter()) + } } impl ToLendingIterator for I {}