From 467af82f3b592c6c04d56b93819c7a57edf2db5a Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Sun, 15 Dec 2024 02:12:19 -0600 Subject: [PATCH 01/16] New design for `EventIterator` --- Cargo.lock | 59 ++++++++++++++++++------------------- Cargo.toml | 3 ++ src/as_event_iter.rs | 14 ++++----- src/enumerate.rs | 52 ++++++++++++++++++--------------- src/event_iter.rs | 61 ++++++++++++++++++++++++--------------- src/filter.rs | 23 ++++++++------- src/filter_map.rs | 21 ++++++++------ src/fuse.rs | 69 ++++++++++++++++++++++++-------------------- src/inspect.rs | 68 +++++++++++++++++++++++++++---------------- src/lib.rs | 56 +++++++++++++++++------------------ src/map.rs | 48 +++++++++++++++--------------- src/next.rs | 19 ++++++------ src/take.rs | 60 ++++++++++++++++++++++---------------- src/take_while.rs | 25 ++++++++-------- src/tear.rs | 68 +++++++++++++++++++++++-------------------- 15 files changed, 356 insertions(+), 290 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0955522..40d122e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,25 +20,26 @@ checksum = "2c61a19d4ab2db23de9a52d0085948e6647c0abd46cf0361de57e6716b65c785" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "event_iterator" -version = "0.2.1" +version = "0.2.2" dependencies = [ "async_main", "futures", "pasts", + "pin-project-lite", "whisk", ] [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -51,9 +52,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -61,15 +62,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -78,15 +79,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -95,21 +96,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -137,9 +138,9 @@ checksum = "efcd36303871fb977a47dabc9af736c75c492bb32a92fa26262b2741531e97ce" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -149,9 +150,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -176,9 +177,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -187,9 +188,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "whisk" diff --git a/Cargo.toml b/Cargo.toml index 3f1fcee..ba9b78e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,9 @@ categories = ["asynchronous", "no-std", "rust-patterns"] readme = "README.md" rust-version = "1.70" +[dependencies.pin-project-lite] +version = "0.2" + [dev-dependencies.async_main] version = "0.4" features = ["pasts"] diff --git a/src/as_event_iter.rs b/src/as_event_iter.rs index 02e3907..8961722 100644 --- a/src/as_event_iter.rs +++ b/src/as_event_iter.rs @@ -14,7 +14,7 @@ pub struct AsEventIter<'b, E>(&'b (dyn DynEventIter<'b, Event = E> + Unpin)); impl<'b, E> AsEventIter<'b, E> { /// Create a new `AsEventIter` from something implementing /// [`EventIterator`]. - pub fn new(ei: &'b (impl EventIterator = E> + Unpin)) -> Self { + pub fn new(ei: &'b mut (impl EventIterator = E> + Unpin)) -> Self { Self(ei) } } @@ -31,10 +31,10 @@ impl EventIterator for AsEventIter<'_, E> { type Event<'me> = E where Self: 'me; fn poll_next( - self: Pin<&Self>, + mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { - Pin::new(&self.0).poll_next(cx) + Pin::new(&mut self.0).poll_next(cx) } } @@ -56,7 +56,7 @@ pub trait AsEventIterator<'b>: Unpin { /// ```rust #[doc = include_str!("../examples/tripple_buffer.rs")] /// ``` - fn as_event_iter(&'b self) -> AsEventIter<'b, Self::Event>; + fn as_event_iter(&'b mut self) -> AsEventIter<'b, Self::Event>; } impl<'b, T> AsEventIterator<'b> for T @@ -65,7 +65,7 @@ where { type Event = ::Event<'b>; - fn as_event_iter(&'b self) -> AsEventIter<'b, Self::Event> { + fn as_event_iter(&'b mut self) -> AsEventIter<'b, Self::Event> { AsEventIter::new(self) } } @@ -73,7 +73,7 @@ where trait DynEventIter<'b> { type Event; - fn poll_next(&'b self, cx: &mut Context<'_>) -> Poll>; + fn poll_next(&'b mut self, cx: &mut Context<'_>) -> Poll>; } impl<'b, T> DynEventIter<'b> for T @@ -82,7 +82,7 @@ where { type Event = ::Event<'b>; - fn poll_next(&'b self, cx: &mut Context<'_>) -> Poll> { + fn poll_next(&'b mut self, cx: &mut Context<'_>) -> Poll> { Pin::new(self).poll_next(cx) } } diff --git a/src/enumerate.rs b/src/enumerate.rs index fcdfd29..ad9a298 100644 --- a/src/enumerate.rs +++ b/src/enumerate.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -7,18 +6,21 @@ use core::{ use crate::EventIterator; -/// Event iterator that yields the current count and event during iteration -/// -/// This `struct` is created by the [`EventIterator::enumerate()`] method. See -/// its documentation for more. -pub struct Enumerate { - ei: I, - count: Cell, +pin_project_lite::pin_project! { + /// Event iterator that yields the current count and event during iteration + /// + /// This `struct` is created by the [`EventIterator::enumerate()`] method. + /// See its documentation for more. + pub struct Enumerate { + #[pin] + ei: I, + count: usize, + } } impl Enumerate { pub(crate) fn new(ei: I) -> Self { - let count = Cell::new(0); + let count = 0; Self { ei, count } } @@ -40,20 +42,24 @@ impl EventIterator for Enumerate where I: EventIterator + Unpin, { - type Event<'me> = (usize, I::Event<'me>) where I: 'me; - - fn poll_next<'a>( - self: Pin<&'a Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); - let Poll::Ready(event) = Pin::new(&this.ei).poll_next(cx) else { - return Poll::Pending; - }; - let count = this.count.get(); - - this.count.set(count + 1); - Poll::Ready(event.map(|e| (count, e))) + type Event<'me> + = (usize, I::Event<'me>) + where + I: 'me; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let this = self.project(); + let poll = this.ei.poll(cx); + + (*this.count) += 1; + poll + } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + let count = *this.count; + + this.ei.event().map(|e| (count, e)) } fn size_hint(&self) -> (usize, Option) { diff --git a/src/event_iter.rs b/src/event_iter.rs index c7ac6cb..612ced0 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -1,20 +1,27 @@ use core::{ - ops::Deref, + ops::{Deref, DerefMut}, pin::Pin, task::{Context, Poll}, }; use crate::{ - Enumerate, Filter, FilterMap, Fuse, Inspect, Map, Next, Take, TakeWhile, + Enumerate, /* Filter, FilterMap, */ Fuse, Inspect, Map, Next, + Take, /* TakeWhile, */ Tear, }; /// Asynchronous lending iterator /// -/// Unlike iterators, the type must only be modified through interior mutability -/// during iteration. This is to get around the limitation of not being able to -/// use [`Pin::as_mut()`] in some situations, due to the fact that events take -/// the lifetime of `Self`, resulting in insufficient lifetimes. +/// Rather than have a single `poll_next()` method as in `Stream` / +/// `AsyncIterator`, event iterators have a separate `poll()` and `event()`. +/// A lot of asynchronous implementation patterns require usage of +/// [`Pin::as_mut()`]. When GATs are in the mix, this is impossible since it +/// reduces the lifetime on your pinned reference to `Self`, which would be +/// insufficient for the return value's lifetime. This design also allows event +/// iterators to have unique semantics. +/// +/// - Event iterators are always `Ready` immediately +/// - Event iterators can be "peeked" /// /// # Example /// @@ -28,8 +35,7 @@ pub trait EventIterator { Self: 'me; /// Attempt to pull out the next event of this event iterator, registering - /// the current task for wakeup if the value is not yet available, and - /// returning `None` if the event iterator is exhausted. + /// the current task for wakeup if the event is not yet available. /// /// # Return value /// @@ -55,10 +61,11 @@ pub trait EventIterator { /// calls must never cause undefined behavior (memory corruption, incorrect /// use of unsafe functions, or the like), regardless of the event /// iterator’s state. - fn poll_next<'a>( - self: Pin<&'a Self>, - cx: &mut Context<'_>, - ) -> Poll>>; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()>; + + /// Attempt to borrow the current event, and return `None` if the event + /// iterator is exhausted. + fn event<'a>(self: Pin<&'a mut Self>) -> Option>; /// Create a future that resolves to the next event in the event iterator. /// @@ -70,7 +77,7 @@ pub trait EventIterator { /// ```rust #[doc = include_str!("../examples/next.rs")] /// ``` - fn next<'a>(self: Pin<&'a Self>) -> Next<'a, Self> + fn next<'a>(self: Pin<&'a mut Self>) -> Next<'a, Self> where Self: Sized, { @@ -87,7 +94,7 @@ pub trait EventIterator { /// ```rust #[doc = include_str!("../examples/next_unpinned.rs")] /// ``` - fn next_unpinned(&self) -> Next<'_, Self> + fn next_unpinned(&mut self) -> Next<'_, Self> where Self: Sized + Unpin, { @@ -166,11 +173,12 @@ pub trait EventIterator { fn map(self, f: F) -> Map where Self: Sized, - F: for<'me> FnMut(Self::Event<'me>) -> B, + F: for<'me> Fn(Self::Event<'me>) -> B, { Map::new(self, f) } + /* /// Create an event iterator which uses a closure to determine if an event /// should be yielded. /// @@ -212,7 +220,7 @@ pub trait EventIterator { F: for<'me> FnMut(Self::Event<'me>) -> Option, { FilterMap::new(self, f) - } + }*/ /// Do something with each event of an event iterator, passing the value on. /// @@ -339,6 +347,7 @@ pub trait EventIterator { Take::new(self, n) } + /* /// Create an event iterator that yields elements based on a predicate. /// /// `take_while()` takes a closure as an argument. It will call this @@ -360,21 +369,25 @@ pub trait EventIterator { { TakeWhile::new(self, predicate) } + */ } impl EventIterator for T where - T: Deref + ?Sized, + T: Deref + DerefMut + ?Sized + Unpin, T::Target: EventIterator + Unpin, { - type Event<'me> = <::Target as EventIterator>::Event<'me> - where Self: 'me; + type Event<'me> + = <::Target as EventIterator>::Event<'me> + where + Self: 'me; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + Pin::new(&mut **self.get_mut()).poll(cx) + } - fn poll_next<'a>( - self: Pin<&'a Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - Pin::new(&**self.get_ref()).poll_next(cx) + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + Pin::new(&mut **self.get_mut()).event() } fn size_hint(&self) -> (usize, Option) { diff --git a/src/filter.rs b/src/filter.rs index 56ddd0e..b8b99eb 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -7,19 +6,21 @@ use core::{ use crate::EventIterator; -/// Event iterator that filters the events of an event iterator with a predicate -/// -/// This `struct` is created by the [`EventIterator::filter()`] method. See its -/// documentation for more. -pub struct Filter { - ei: I, - p: Cell>, +pin_project_lite::pin_project! { + /// Event iterator that filters the events of an event iterator with a + /// predicate + /// + /// This `struct` is created by the [`EventIterator::filter()`] method. See + /// its documentation for more. + pub struct Filter { + #[pin] + ei: I, + p: P, + } } impl Filter { pub(crate) fn new(ei: I, p: P) -> Self { - let p = Cell::new(Some(p)); - Self { ei, p } } } @@ -43,7 +44,7 @@ where type Event<'me> = I::Event<'me> where I: 'me; fn poll_next<'a>( - self: Pin<&'a Self>, + self: Pin<&'a mut Self>, cx: &mut Context<'_>, ) -> Poll>> { let this = self.get_ref(); diff --git a/src/filter_map.rs b/src/filter_map.rs index 548d232..df27d89 100644 --- a/src/filter_map.rs +++ b/src/filter_map.rs @@ -7,13 +7,16 @@ use core::{ use crate::EventIterator; -/// Event iterator that uses a closure to both filter and map events -/// -/// This `struct` is created by the [`EventIterator::filter_map()`] method. See -/// its documentation for more. -pub struct FilterMap { - ei: I, - f: Cell>, +pin_project_lite::pin_project! { + /// Event iterator that uses a closure to both filter and map events + /// + /// This `struct` is created by the [`EventIterator::filter_map()`] method. + /// See its documentation for more. + pub struct FilterMap { + #[pin] + ei: I, + f: F, + } } impl FilterMap { @@ -43,10 +46,10 @@ where type Event<'me> = B where I: 'me; fn poll_next<'a>( - self: Pin<&'a Self>, + self: Pin<&'a mut Self>, cx: &mut Context<'_>, ) -> Poll>> { - let this = self.get_ref(); + let this = self.project(); loop { let Poll::Ready(event) = Pin::new(&this.ei).poll_next(cx) else { diff --git a/src/fuse.rs b/src/fuse.rs index e7cab31..8105f84 100644 --- a/src/fuse.rs +++ b/src/fuse.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -7,15 +6,18 @@ use core::{ use crate::EventIterator; -/// Event iterator that returns `Ready(None)` forever after it's finished -/// -/// An event iterator is finished after it first returns `Ready(None)`. -/// -/// This `struct` is created by the [`EventIterator::fuse()`] method. See its -/// documentation for more. -pub struct Fuse { - ei: I, - ended: Cell, +pin_project_lite::pin_project! { + /// Event iterator that returns `Ready(None)` forever after it's finished + /// + /// An event iterator is finished after it first returns `Ready(None)`. + /// + /// This `struct` is created by the [`EventIterator::fuse()`] method. See + /// its documentation for more. + #[repr(transparent)] + pub struct Fuse { + #[pin] + ei: Option, + } } impl fmt::Debug for Fuse @@ -23,18 +25,13 @@ where I: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Fuse") - .field("ei", &self.ei) - .field("ended", &self.ended) - .finish() + f.debug_struct("Fuse").field("ei", &self.ei).finish() } } impl Fuse { pub(crate) fn new(ei: I) -> Self { - let ended = Cell::new(false); - - Self { ei, ended } + Self { ei: Some(ei) } } } @@ -42,28 +39,38 @@ impl EventIterator for Fuse where I: EventIterator + Unpin, { - type Event<'me> = I::Event<'me> where I: 'me; + type Event<'me> + = I::Event<'me> + where + I: 'me; - fn poll_next<'a>( - self: Pin<&'a Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let this = self.project(); + let Some(ei) = this.ei.as_pin_mut() else { + return Poll::Ready(()); + }; - if this.ended.get() { - return Poll::Ready(None); - } + ei.poll(cx) + } - let poll = Pin::new(&this.ei).poll_next(cx); + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let mut this = self.project(); + let Some(ei) = this.ei.as_mut().as_pin_mut() else { + return None; + }; - if let Poll::Ready(None) = poll { - this.ended.set(true); + if ei.event().is_none() { + (*this.ei) = None; + return None; } - poll + this.ei.as_pin_mut().and_then(|ei| ei.event()) } fn size_hint(&self) -> (usize, Option) { - self.ei.size_hint() + self.ei + .as_ref() + .map(|ei| ei.size_hint()) + .unwrap_or((0, Some(0))) } } diff --git a/src/inspect.rs b/src/inspect.rs index d06b770..0976f1a 100644 --- a/src/inspect.rs +++ b/src/inspect.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -7,20 +6,28 @@ use core::{ use crate::EventIterator; -/// Event iterator that calls a closure with a reference to each event -/// -/// This `struct` is created by the [`EventIterator::map()`] method. See its -/// documentation for more. -pub struct Inspect { - ei: I, - f: Cell>, +pin_project_lite::pin_project! { + /// Event iterator that calls a closure with a reference to each event + /// + /// This `struct` is created by the [`EventIterator::inspect()`] method. + /// See its documentation for more. + pub struct Inspect { + #[pin] + ei: I, + f: F, + needs_inspection: bool, + } } impl Inspect { pub(crate) fn new(ei: I, f: F) -> Self { - let f = Cell::new(Some(f)); + let needs_inspection = true; - Self { ei, f } + Self { + ei, + f, + needs_inspection, + } } } @@ -31,6 +38,7 @@ where fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Inspect") .field("ei", &self.ei) + .field("needs_inspection", &self.needs_inspection) .finish_non_exhaustive() } } @@ -38,26 +46,36 @@ where impl EventIterator for Inspect where I: EventIterator + Unpin, - F: for<'me> FnMut(&I::Event<'me>) + 'static + Unpin, + F: for<'me> FnMut(&I::Event<'me>) + 'static, { - type Event<'me> = I::Event<'me> where I: 'me; + type Event<'me> + = I::Event<'me> + where + I: 'me; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + self.as_mut().event(); + + let this = self.project(); + let poll = this.ei.poll(cx); + + if poll.is_ready() { + (*this.needs_inspection) = true; + } + + poll + } - fn poll_next<'a>( - self: Pin<&'a Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); - let event = Pin::new(&this.ei).poll_next(cx); - let Poll::Ready(Some(event)) = event else { - return event; - }; + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + let event = this.ei.event()?; - if let Some(mut f) = this.f.take() { - f(&event); - this.f.set(Some(f)); + if *this.needs_inspection { + (*this.needs_inspection) = false; + (*this.f)(&event); } - Poll::Ready(Some(event)) + Some(event) } fn size_hint(&self) -> (usize, Option) { diff --git a/src/lib.rs b/src/lib.rs index f6116e4..15889d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,50 +42,50 @@ variant_size_differences )] -mod as_event_iter; -mod empty; +//mod as_event_iter; +//mod empty; mod enumerate; mod event_iter; -mod filter; -mod filter_map; -mod from_fn; -mod from_iter; +//mod filter; +//mod filter_map; +//mod from_fn; +//mod from_iter; mod fuse; mod inspect; mod map; mod next; -mod once; -mod once_with; -mod pending; -mod poll_fn; -mod ready; -mod repeat; -mod repeat_with; +//mod once; +//mod once_with; +//mod pending; +//mod poll_fn; +//mod ready; +//mod repeat; +//mod repeat_with; mod take; -mod take_while; +//mod take_while; mod tear; pub use self::{ - as_event_iter::{AsEventIter, AsEventIterator}, - empty::{empty, Empty}, + // as_event_iter::{AsEventIter, AsEventIterator}, + // empty::{empty, Empty}, enumerate::Enumerate, event_iter::EventIterator, - filter::Filter, - filter_map::FilterMap, - from_fn::{from_fn, FromFn}, - from_iter::{from_iter, FromIter}, + // filter::Filter, + // filter_map::FilterMap, + // from_fn::{from_fn, FromFn}, + // from_iter::{from_iter, FromIter}, fuse::Fuse, inspect::Inspect, map::Map, next::Next, - once::{once, Once}, - once_with::{once_with, OnceWith}, - pending::{pending, Pending}, - poll_fn::{poll_fn, PollFn}, - ready::{ready, Ready}, - repeat::{repeat, Repeat}, - repeat_with::{repeat_with, RepeatWith}, + // once::{once, Once}, + // once_with::{once_with, OnceWith}, + // pending::{pending, Pending}, + // poll_fn::{poll_fn, PollFn}, + // ready::{ready, Ready}, + // repeat::{repeat, Repeat}, + // repeat_with::{repeat_with, RepeatWith}, take::Take, - take_while::TakeWhile, + // take_while::TakeWhile, tear::Tear, }; diff --git a/src/map.rs b/src/map.rs index 4a45deb..1715d1d 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -7,19 +6,20 @@ use core::{ use crate::EventIterator; -/// Event iterator that maps the events with a closure -/// -/// This `struct` is created by the [`EventIterator::map()`] method. See its -/// documentation for more. -pub struct Map { - ei: I, - f: Cell>, +pin_project_lite::pin_project! { + /// Event iterator that maps the events with a closure + /// + /// This `struct` is created by the [`EventIterator::map()`] method. See + /// its documentation for more. + pub struct Map { + #[pin] + ei: I, + f: F, + } } impl Map { pub(crate) fn new(ei: I, f: F) -> Self { - let f = Cell::new(Some(f)); - Self { ei, f } } } @@ -38,25 +38,23 @@ where impl EventIterator for Map where I: EventIterator + Unpin, - F: for<'me> FnMut(I::Event<'me>) -> B + 'static + Unpin, + F: for<'me> Fn(I::Event<'me>) -> B + 'static, { - type Event<'me> = B where I: 'me; + type Event<'me> + = B + where + I: 'me; - fn poll_next<'a>( - self: Pin<&'a Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); - let Poll::Ready(event) = Pin::new(&this.ei).poll_next(cx) else { - return Poll::Pending; - }; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let this = self.project(); + + this.ei.poll(cx) + } - Poll::Ready(this.f.take().and_then(|mut f| { - let event = event.map(&mut f); + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); - this.f.set(Some(f)); - event - })) + this.ei.event().map(this.f) } fn size_hint(&self) -> (usize, Option) { diff --git a/src/next.rs b/src/next.rs index b47cac9..3f7b8eb 100644 --- a/src/next.rs +++ b/src/next.rs @@ -12,10 +12,10 @@ use crate::EventIterator; /// [`next_unpinned()`](EventIterator::next_unpinned) methods. See their /// documentation for more. #[derive(Debug)] -pub struct Next<'a, Ei>(Option>); +pub struct Next<'a, Ei>(Option>); impl<'a, Ei> Next<'a, Ei> { - pub(crate) fn new(ei: Pin<&'a Ei>) -> Self { + pub(crate) fn new(ei: Pin<&'a mut Ei>) -> Self { Self(Some(ei)) } } @@ -28,15 +28,14 @@ where fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.get_mut(); - let Some(ei) = this.0.as_ref() else { - return Poll::Ready(None); + let Some(mut ei) = this.0.take() else { + return Poll::Pending; + }; + let Poll::Ready(()) = ei.as_mut().poll(cx) else { + this.0 = Some(ei); + return Poll::Pending; }; - let output = ei.poll_next(cx); - - if output.is_ready() { - this.0 = None; - } - output + Poll::Ready(ei.event()) } } diff --git a/src/take.rs b/src/take.rs index 44550bb..a89d694 100644 --- a/src/take.rs +++ b/src/take.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -7,19 +6,20 @@ use core::{ use crate::EventIterator; -/// Event iterator that only yields a specified number of events -/// -/// This `struct` is created by the [`EventIterator::take()`] method. See its -/// documentation for more. -pub struct Take { - ei: I, - count: Cell, +pin_project_lite::pin_project! { + /// Event iterator that only yields a specified number of events + /// + /// This `struct` is created by the [`EventIterator::take()`] method. See + /// its documentation for more. + pub struct Take { + #[pin] + ei: I, + count: usize, + } } impl Take { pub(crate) fn new(ei: I, count: usize) -> Self { - let count = Cell::new(count); - Self { ei, count } } } @@ -40,29 +40,39 @@ impl EventIterator for Take where I: EventIterator + Unpin, { - type Event<'me> = I::Event<'me> where I: 'me; + type Event<'me> + = I::Event<'me> + where + I: 'me; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let this = self.project(); - fn poll_next<'a>( - self: Pin<&'a Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); - let count = this.count.get(); + if *this.count == 0 { + return Poll::Ready(()) + } - if count == 0 { - return Poll::Ready(None); + let poll = this.ei.poll(cx); + + if poll.is_ready() { + (*this.count) -= 1; } - let Poll::Ready(event) = Pin::new(&this.ei).poll_next(cx) else { - return Poll::Pending; - }; + poll + } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + + if *this.count == 0 { + return None + } - this.count.set(count - 1); - Poll::Ready(event) + this.ei.event() } fn size_hint(&self) -> (usize, Option) { - let count = self.count.get(); + let count = self.count; if count == 0 { return (0, Some(0)); diff --git a/src/take_while.rs b/src/take_while.rs index f84bc00..b1aba80 100644 --- a/src/take_while.rs +++ b/src/take_while.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -7,19 +6,21 @@ use core::{ use crate::EventIterator; -/// Event iterator that only yields elements while a predicate returns `true` -/// -/// This `struct` is created by the [`EventIterator::take_while()`] method. See -/// its documentation for more. -pub struct TakeWhile { - ei: I, - p: Cell>, +pin_project_lite::pin_project! { + /// Event iterator that only yields elements while a predicate returns + /// `true` + /// + /// This `struct` is created by the [`EventIterator::take_while()`] method. + /// See its documentation for more. + pub struct TakeWhile { + #[pin] + ei: I, + p: P, + } } impl TakeWhile { pub(crate) fn new(ei: I, p: P) -> Self { - let p = Cell::new(Some(p)); - Self { ei, p } } } @@ -43,10 +44,10 @@ where type Event<'me> = I::Event<'me> where I: 'me; fn poll_next<'a>( - self: Pin<&'a Self>, + self: Pin<&'a mut Self>, cx: &mut Context<'_>, ) -> Poll>> { - let this = self.get_ref(); + let this = self.project(); loop { let Poll::Ready(event) = Pin::new(&this.ei).poll_next(cx) else { diff --git a/src/tear.rs b/src/tear.rs index a5b3e1c..2528f3f 100644 --- a/src/tear.rs +++ b/src/tear.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -7,15 +6,17 @@ use core::{ use crate::EventIterator; -/// Event iterator that returns `Pending` forever after it's finished -/// -/// An event iterator is finished after it first returns `Ready(None)`. -/// -/// This `struct` is created by the [`EventIterator::tear()`] method. See -/// its documentation for more. -pub struct Tear { - ei: I, - ended: Cell, +pin_project_lite::pin_project! { + /// Event iterator that returns `Pending` forever after it's finished + /// + /// An event iterator is finished after it first returns `Ready(None)`. + /// + /// This `struct` is created by the [`EventIterator::tear()`] method. See + /// its documentation for more. + pub struct Tear { + #[pin] + ei: Option, + } } impl fmt::Debug for Tear @@ -23,18 +24,13 @@ where I: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Tear") - .field("ei", &self.ei) - .field("ended", &self.ended) - .finish() + f.debug_struct("Tear").field("ei", &self.ei).finish() } } impl Tear { pub(crate) fn new(ei: I) -> Self { - let ended = Cell::new(false); - - Self { ei, ended } + Self { ei: Some(ei) } } } @@ -42,28 +38,38 @@ impl EventIterator for Tear where I: EventIterator + Unpin, { - type Event<'me> = I::Event<'me> where I: 'me; - - fn poll_next<'a>( - self: Pin<&'a Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); + type Event<'me> + = I::Event<'me> + where + I: 'me; - if this.ended.get() { + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let this = self.project(); + let Some(ei) = this.ei.as_pin_mut() else { return Poll::Pending; - } + }; + + ei.poll(cx) + } - let poll = Pin::new(&this.ei).poll_next(cx); + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let mut this = self.project(); + let Some(ei) = this.ei.as_mut().as_pin_mut() else { + return None; + }; - if let Poll::Ready(None) = poll { - this.ended.set(true); + if ei.event().is_none() { + (*this.ei) = None; + return None; } - poll + this.ei.as_pin_mut().and_then(|ei| ei.event()) } fn size_hint(&self) -> (usize, Option) { - self.ei.size_hint() + self.ei + .as_ref() + .map(|ei| ei.size_hint()) + .unwrap_or((0, Some(0))) } } From b31ea2f179edba48e918723095f95a686ff3b058 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Mon, 16 Dec 2024 15:58:46 -0600 Subject: [PATCH 02/16] Some changes --- examples/enumerate.rs | 9 ++-- examples/from_iter.rs | 4 +- examples/from_iter_mut.rs | 10 ++++ examples/map.rs | 4 +- src/consts.rs | 2 + src/enumerate.rs | 13 ++++-- src/event_iter.rs | 50 ++++++++++++-------- src/from_iter.rs | 81 +++++++++++++++++++------------- src/from_iter_mut.rs | 98 +++++++++++++++++++++++++++++++++++++++ src/inspect.rs | 28 ++++------- src/lib.rs | 7 ++- src/map.rs | 32 ++++++++----- src/take.rs | 8 ++-- 13 files changed, 241 insertions(+), 105 deletions(-) create mode 100644 examples/from_iter_mut.rs create mode 100644 src/consts.rs create mode 100644 src/from_iter_mut.rs diff --git a/examples/enumerate.rs b/examples/enumerate.rs index 4205e7c..d85ca69 100644 --- a/examples/enumerate.rs +++ b/examples/enumerate.rs @@ -2,11 +2,10 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter(['a', 'b', 'c']); - let ei = ei.enumerate(); + let mut ei = event_iterator::from_iter(['a', 'b', 'c']).enumerate(); - assert_eq!(ei.next_unpinned().await, Some((0, 'a'))); - assert_eq!(ei.next_unpinned().await, Some((1, 'b'))); - assert_eq!(ei.next_unpinned().await, Some((2, 'c'))); + assert_eq!(ei.next_unpinned().await, Some((0, &'a'))); + assert_eq!(ei.next_unpinned().await, Some((1, &'b'))); + assert_eq!(ei.next_unpinned().await, Some((2, &'c'))); assert_eq!(ei.next_unpinned().await, None); } diff --git a/examples/from_iter.rs b/examples/from_iter.rs index c82966b..ff3c06a 100644 --- a/examples/from_iter.rs +++ b/examples/from_iter.rs @@ -2,9 +2,9 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([1, 2, 3, 4, 5]); + let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]); - while let Some(i) = ei.next_unpinned().await { + while let Some(&i) = ei.next_unpinned().await { println!("{i}"); } } diff --git a/examples/from_iter_mut.rs b/examples/from_iter_mut.rs new file mode 100644 index 0000000..5f5be5a --- /dev/null +++ b/examples/from_iter_mut.rs @@ -0,0 +1,10 @@ +use event_iterator::EventIterator; + +#[async_main::async_main] +async fn main(_spawner: async_main::LocalSpawner) { + let mut ei = event_iterator::from_iter_mut([1, 2, 3, 4, 5]); + + while let Some(&mut i) = ei.next_unpinned().await { + println!("{i}"); + } +} diff --git a/examples/map.rs b/examples/map.rs index d2c4f7b..70cc4ad 100644 --- a/examples/map.rs +++ b/examples/map.rs @@ -2,8 +2,8 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = - event_iterator::from_iter([1, 2, 3, 4, 5]).map(|x| "uwu".repeat(x)); + let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]) + .map(|&mut x| "uwu".repeat(x)); while let Some(i) = ei.next_unpinned().await { println!("{i}"); diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 0000000..9f3a1c1 --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,2 @@ +pub(crate) const EVENT_BEFORE_POLL: &str = + "tried to lend event before first poll"; diff --git a/src/enumerate.rs b/src/enumerate.rs index ad9a298..9ff238c 100644 --- a/src/enumerate.rs +++ b/src/enumerate.rs @@ -4,7 +4,7 @@ use core::{ task::{Context, Poll}, }; -use crate::EventIterator; +use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; pin_project_lite::pin_project! { /// Event iterator that yields the current count and event during iteration @@ -14,13 +14,13 @@ pin_project_lite::pin_project! { pub struct Enumerate { #[pin] ei: I, - count: usize, + count: Option, } } impl Enumerate { pub(crate) fn new(ei: I) -> Self { - let count = 0; + let count = None; Self { ei, count } } @@ -51,13 +51,16 @@ where let this = self.project(); let poll = this.ei.poll(cx); - (*this.count) += 1; + if poll.is_ready() { + (*this.count) = Some((*this.count).map(|c| c + 1).unwrap_or(0)); + } + poll } fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let this = self.project(); - let count = *this.count; + let count = (*this.count).expect(EVENT_BEFORE_POLL); this.ei.event().map(|e| (count, e)) } diff --git a/src/event_iter.rs b/src/event_iter.rs index 612ced0..84eed66 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -13,15 +13,12 @@ use crate::{ /// Asynchronous lending iterator /// /// Rather than have a single `poll_next()` method as in `Stream` / -/// `AsyncIterator`, event iterators have a separate `poll()` and `event()`. -/// A lot of asynchronous implementation patterns require usage of -/// [`Pin::as_mut()`]. When GATs are in the mix, this is impossible since it -/// reduces the lifetime on your pinned reference to `Self`, which would be -/// insufficient for the return value's lifetime. This design also allows event -/// iterators to have unique semantics. -/// -/// - Event iterators are always `Ready` immediately -/// - Event iterators can be "peeked" +/// `AsyncIterator`, event iterators have separate `poll()` and `event()` +/// methods for polling and lending. Why? A lot of asynchronous implementation +/// patterns require usage of [`Pin::as_mut()`]. When GATs are in the mix, this +/// usage is impossible since it reduces the lifetime on your pinned reference +/// to `Self`, which would be insufficient for a returned +/// `Poll>>` lifetime. /// /// # Example /// @@ -53,18 +50,28 @@ pub trait EventIterator { /// /// # Panics /// - /// Once an event iterator has finished (returned `Ready(None)` from - /// `poll_next()`), calling its `poll_next()` method again may panic, block - /// forever, or cause other kinds of problems; the `EventIterator` trait - /// places no requirements on the effects of such a call. However, as the - /// `poll_next()` method is not marked unsafe, Rust’s usual rules apply: - /// calls must never cause undefined behavior (memory corruption, incorrect - /// use of unsafe functions, or the like), regardless of the event - /// iterator’s state. + /// Once an event iterator has finished (returned `Ready` from `poll()` with + /// `event()` returning `None`), calling its `poll()` method again may + /// panic, block forever, or cause other kinds of problems; the + /// `EventIterator` trait places no requirements on the effects of such a + /// call. However, as the `poll()` method is not marked unsafe, Rust’s + /// usual rules apply: calls must never cause undefined behavior (memory + /// corruption, incorrect use of unsafe functions, or the like), regardless + /// of the event iterator’s state. fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()>; /// Attempt to borrow the current event, and return `None` if the event /// iterator is exhausted. + /// + /// # Panics + /// + /// Calling `event()` before `poll()` may panic, block forever or cause + /// other kinds of problems; the `EventIterator` trait places no + /// requirements on the effects of such a call. However, as the + /// `poll_next()` method is not marked unsafe, Rust’s usual rules apply: + /// calls must never cause undefined behavior (memory corruption, incorrect + /// use of unsafe functions, or the like), regardless of the event + /// iterator’s state. fn event<'a>(self: Pin<&'a mut Self>) -> Option>; /// Create a future that resolves to the next event in the event iterator. @@ -170,10 +177,10 @@ pub trait EventIterator { /// uwuuwuuwuuwu /// uwuuwuuwuuwuuwu /// ``` - fn map(self, f: F) -> Map + fn map(self, f: F) -> Map where Self: Sized, - F: for<'me> Fn(Self::Event<'me>) -> B, + F: for<'me> FnMut(Self::Event<'me>) -> E, { Map::new(self, f) } @@ -245,7 +252,7 @@ pub trait EventIterator { fn inspect(self, f: F) -> Inspect where Self: Sized, - F: for<'me> FnMut(&Self::Event<'me>), + F: for<'me> FnMut(Self::Event<'me>), { Inspect::new(self, f) } @@ -270,6 +277,9 @@ pub trait EventIterator { /// The returned event iterator might panic if the to-be-returned index /// would overflow a [`usize`]. /// + /// The returned event iterator might panic if [`EventIterator::event()`] is + /// called before [`EventIterator::poll()`]. + /// /// # Example /// /// ```rust diff --git a/src/from_iter.rs b/src/from_iter.rs index a7e2001..0ce8ce8 100644 --- a/src/from_iter.rs +++ b/src/from_iter.rs @@ -1,65 +1,72 @@ use core::{ - cell::Cell, fmt, + iter::Peekable, pin::Pin, task::{Context, Poll}, }; -use crate::EventIterator; +use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; /// Event iterator that was created from an iterator /// /// This event iterator is created by the [`from_iter()`] function. See its /// documentation for more. -pub struct FromIter(Cell>); +pub struct FromIter +where + I: Iterator, +{ + iter: Peekable, + started: bool, +} impl fmt::Debug for FromIter where - I: fmt::Debug, + I: Iterator + fmt::Debug, + ::Item: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let iter = self.0.take(); - let result = f.debug_tuple("FromIter").field(&iter).finish(); - - self.0.set(iter); - result + f.debug_tuple("FromIter").field(&self.iter).finish() } } -impl Unpin for FromIter {} - impl EventIterator for FromIter where - I: Iterator, + I: Iterator + Unpin, + ::Item: Unpin, { - type Event<'me> = ::Item where I: 'me; + type Event<'me> + = &'me ::Item + where + I: 'me; + + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { + let this = self.get_mut(); - fn poll_next<'a>( - self: Pin<&'a Self>, - _cx: &mut Context<'_>, - ) -> Poll>> { - Poll::Ready(self.0.take().and_then(|mut iter| { - let item = iter.next()?; + if this.started { + _ = this.iter.next(); + } else { + this.started = true; + } - self.0.set(Some(iter)); - Some(item) - })) + Poll::Ready(()) } - fn size_hint(&self) -> (usize, Option) { - self.0 - .take() - .map(|iter| { - let size = iter.size_hint(); + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.get_mut(); + + if this.started == false { + panic!("{EVENT_BEFORE_POLL}"); + } + + this.iter.peek() + } - self.0.set(Some(iter)); - size - }) - .unwrap_or((0, Some(0))) + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() } } -/// Convert an iterator into an event iterator. +/// Convert an iterator into an event iterator of references. /// /// # Example /// @@ -75,9 +82,17 @@ where /// 4 /// 5 /// ``` +/// +/// # Panics +/// +/// The returned event iterator might panic if [`EventIterator::event()`] is +/// called before [`EventIterator::poll()`]. pub fn from_iter(iter: I) -> FromIter<::IntoIter> where I: IntoIterator, { - FromIter(Cell::new(iter.into_iter().into())) + FromIter { + iter: iter.into_iter().peekable(), + started: false, + } } diff --git a/src/from_iter_mut.rs b/src/from_iter_mut.rs new file mode 100644 index 0000000..e5f83e8 --- /dev/null +++ b/src/from_iter_mut.rs @@ -0,0 +1,98 @@ +use core::{ + fmt, + iter::Peekable, + pin::Pin, + task::{Context, Poll}, +}; + +use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; + +/// Event iterator that was created from an iterator +/// +/// This event iterator is created by the [`from_iter_mut()`] function. See its +/// documentation for more. +pub struct FromIterMut +where + I: Iterator, +{ + iter: Peekable, + started: bool, +} + +impl fmt::Debug for FromIterMut +where + I: Iterator + fmt::Debug, + ::Item: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("FromIterMut").field(&self.iter).finish() + } +} + +impl EventIterator for FromIterMut +where + I: Iterator + Unpin, + ::Item: Unpin, +{ + type Event<'me> + = &'me mut ::Item + where + I: 'me; + + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { + let this = self.get_mut(); + + if this.started { + _ = this.iter.next(); + } else { + this.started = true; + } + + Poll::Ready(()) + } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.get_mut(); + + if this.started == false { + panic!("{EVENT_BEFORE_POLL}"); + } + + this.iter.peek_mut() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +/// Convert an iterator into an event iterator of exclusive references. +/// +/// # Example +/// +/// ```rust +#[doc = include_str!("../examples/from_iter_mut.rs")] +/// ``` +/// +/// Output: +/// ```console +/// 1 +/// 2 +/// 3 +/// 4 +/// 5 +/// ``` +/// +/// # Panics +/// +/// The returned event iterator might panic if [`EventIterator::event()`] is +/// called before [`EventIterator::poll()`]. +pub fn from_iter_mut(iter: I) -> FromIterMut<::IntoIter> +where + I: IntoIterator, +{ + FromIterMut { + iter: iter.into_iter().peekable(), + started: false, + } +} diff --git a/src/inspect.rs b/src/inspect.rs index 0976f1a..17503f0 100644 --- a/src/inspect.rs +++ b/src/inspect.rs @@ -15,19 +15,12 @@ pin_project_lite::pin_project! { #[pin] ei: I, f: F, - needs_inspection: bool, } } impl Inspect { pub(crate) fn new(ei: I, f: F) -> Self { - let needs_inspection = true; - - Self { - ei, - f, - needs_inspection, - } + Self { ei, f } } } @@ -38,7 +31,6 @@ where fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Inspect") .field("ei", &self.ei) - .field("needs_inspection", &self.needs_inspection) .finish_non_exhaustive() } } @@ -46,7 +38,7 @@ where impl EventIterator for Inspect where I: EventIterator + Unpin, - F: for<'me> FnMut(&I::Event<'me>) + 'static, + F: for<'me> FnMut(I::Event<'me>) + 'static, { type Event<'me> = I::Event<'me> @@ -56,11 +48,13 @@ where fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { self.as_mut().event(); - let this = self.project(); - let poll = this.ei.poll(cx); + let mut this = self.project(); + let poll = this.ei.as_mut().poll(cx); if poll.is_ready() { - (*this.needs_inspection) = true; + if let Some(event) = this.ei.event() { + (*this.f)(event); + } } poll @@ -68,14 +62,8 @@ where fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let this = self.project(); - let event = this.ei.event()?; - - if *this.needs_inspection { - (*this.needs_inspection) = false; - (*this.f)(&event); - } - Some(event) + this.ei.event() } fn size_hint(&self) -> (usize, Option) { diff --git a/src/lib.rs b/src/lib.rs index 15889d5..72fef1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,9 @@ mod event_iter; //mod filter; //mod filter_map; //mod from_fn; -//mod from_iter; +mod consts; +mod from_iter; +mod from_iter_mut; mod fuse; mod inspect; mod map; @@ -73,7 +75,8 @@ pub use self::{ // filter::Filter, // filter_map::FilterMap, // from_fn::{from_fn, FromFn}, - // from_iter::{from_iter, FromIter}, + from_iter::{from_iter, FromIter}, + from_iter_mut::{from_iter_mut, FromIterMut}, fuse::Fuse, inspect::Inspect, map::Map, diff --git a/src/map.rs b/src/map.rs index 1715d1d..fc269de 100644 --- a/src/map.rs +++ b/src/map.rs @@ -11,20 +11,23 @@ pin_project_lite::pin_project! { /// /// This `struct` is created by the [`EventIterator::map()`] method. See /// its documentation for more. - pub struct Map { + pub struct Map { #[pin] ei: I, f: F, + event: Option, } } -impl Map { +impl Map { pub(crate) fn new(ei: I, f: F) -> Self { - Self { ei, f } + let event = None; + + Self { ei, f, event } } } -impl fmt::Debug for Map +impl fmt::Debug for Map where I: fmt::Debug, { @@ -35,26 +38,31 @@ where } } -impl EventIterator for Map +impl EventIterator for Map where - I: EventIterator + Unpin, - F: for<'me> Fn(I::Event<'me>) -> B + 'static, + I: EventIterator, + F: for<'me> FnMut(I::Event<'me>) -> E, { type Event<'me> - = B + = &'me E where - I: 'me; + Self: 'me; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { - let this = self.project(); + let mut this = self.project(); + let poll = this.ei.as_mut().poll(cx); + + if poll.is_ready() { + (*this.event) = this.ei.event().map(this.f); + } - this.ei.poll(cx) + poll } fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let this = self.project(); - this.ei.event().map(this.f) + this.event.as_ref() } fn size_hint(&self) -> (usize, Option) { diff --git a/src/take.rs b/src/take.rs index a89d694..2eaafcf 100644 --- a/src/take.rs +++ b/src/take.rs @@ -44,12 +44,12 @@ where = I::Event<'me> where I: 'me; - + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { let this = self.project(); if *this.count == 0 { - return Poll::Ready(()) + return Poll::Ready(()); } let poll = this.ei.poll(cx); @@ -63,9 +63,9 @@ where fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let this = self.project(); - + if *this.count == 0 { - return None + return None; } this.ei.event() From 21b31a40e4e23bca94cf3a80250512b5a7427a3d Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Mon, 16 Dec 2024 21:37:02 -0600 Subject: [PATCH 03/16] Rename `next()` / `next_unpinned()` to `next_pinned()` / `next()` --- examples/enumerate.rs | 8 ++-- examples/from_iter.rs | 4 +- examples/from_iter_mut.rs | 2 +- examples/fuse.rs | 12 +++--- examples/inspect.rs | 4 +- examples/map.rs | 4 +- examples/next.rs | 12 +++--- examples/next_pinned.rs | 13 ++++++ examples/next_unpinned.rs | 11 ----- examples/size_hint.rs | 4 +- examples/take.rs | 37 +++++++++-------- examples/tear.rs | 14 +++---- src/event_iter.rs | 87 +++++++++++++++++++-------------------- src/from_iter.rs | 8 +++- src/from_iter_mut.rs | 8 +++- src/inspect.rs | 4 +- src/next.rs | 2 +- src/take.rs | 2 + 18 files changed, 123 insertions(+), 113 deletions(-) create mode 100644 examples/next_pinned.rs delete mode 100644 examples/next_unpinned.rs diff --git a/examples/enumerate.rs b/examples/enumerate.rs index d85ca69..7840d08 100644 --- a/examples/enumerate.rs +++ b/examples/enumerate.rs @@ -4,8 +4,8 @@ use event_iterator::EventIterator; async fn main(_spawner: async_main::LocalSpawner) { let mut ei = event_iterator::from_iter(['a', 'b', 'c']).enumerate(); - assert_eq!(ei.next_unpinned().await, Some((0, &'a'))); - assert_eq!(ei.next_unpinned().await, Some((1, &'b'))); - assert_eq!(ei.next_unpinned().await, Some((2, &'c'))); - assert_eq!(ei.next_unpinned().await, None); + assert_eq!(ei.next().await, Some((0, &'a'))); + assert_eq!(ei.next().await, Some((1, &'b'))); + assert_eq!(ei.next().await, Some((2, &'c'))); + assert_eq!(ei.next().await, None); } diff --git a/examples/from_iter.rs b/examples/from_iter.rs index ff3c06a..2ccf42e 100644 --- a/examples/from_iter.rs +++ b/examples/from_iter.rs @@ -2,9 +2,9 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]); + let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]); - while let Some(&i) = ei.next_unpinned().await { + while let Some(&i) = ei.next().await { println!("{i}"); } } diff --git a/examples/from_iter_mut.rs b/examples/from_iter_mut.rs index 5f5be5a..5bfa9cc 100644 --- a/examples/from_iter_mut.rs +++ b/examples/from_iter_mut.rs @@ -4,7 +4,7 @@ use event_iterator::EventIterator; async fn main(_spawner: async_main::LocalSpawner) { let mut ei = event_iterator::from_iter_mut([1, 2, 3, 4, 5]); - while let Some(&mut i) = ei.next_unpinned().await { + while let Some(&mut i) = ei.next().await { println!("{i}"); } } diff --git a/examples/fuse.rs b/examples/fuse.rs index 10a8efd..7542f6b 100644 --- a/examples/fuse.rs +++ b/examples/fuse.rs @@ -4,11 +4,11 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([1, 2, 3]).fuse(); + let mut ei = event_iterator::from_iter([1, 2, 3]).fuse(); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(Some(1))); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(Some(2))); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(Some(3))); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(None)); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(None)); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&1))); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&2))); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&3))); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(None)); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(None)); } diff --git a/examples/inspect.rs b/examples/inspect.rs index 85dc4c5..ab4c95f 100644 --- a/examples/inspect.rs +++ b/examples/inspect.rs @@ -2,11 +2,11 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([1, 2, 3, 4, 5]).inspect(|&x| { + let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]).inspect(|&x| { let uwu = "uwu".repeat(x); println!("{uwu}"); }); - while ei.next_unpinned().await.is_some() {} + while ei.next().await.is_some() {} } diff --git a/examples/map.rs b/examples/map.rs index 70cc4ad..e8bb2fb 100644 --- a/examples/map.rs +++ b/examples/map.rs @@ -3,9 +3,9 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]) - .map(|&mut x| "uwu".repeat(x)); + .map(|&x| "uwu".repeat(x)); - while let Some(i) = ei.next_unpinned().await { + while let Some(i) = ei.next().await { println!("{i}"); } } diff --git a/examples/next.rs b/examples/next.rs index c9c7d12..700edad 100644 --- a/examples/next.rs +++ b/examples/next.rs @@ -1,13 +1,11 @@ -use std::pin::pin; - use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = pin!(event_iterator::from_iter([3, 1, 2])); + let mut ei = event_iterator::from_iter([3, 1, 2]); - assert_eq!(Some(3), ei.as_ref().next().await); - assert_eq!(Some(1), ei.as_ref().next().await); - assert_eq!(Some(2), ei.as_ref().next().await); - assert_eq!(None, ei.as_ref().next().await); + assert_eq!(Some(&3), ei.next().await); + assert_eq!(Some(&1), ei.next().await); + assert_eq!(Some(&2), ei.next().await); + assert_eq!(None, ei.next().await); } diff --git a/examples/next_pinned.rs b/examples/next_pinned.rs new file mode 100644 index 0000000..5f0e372 --- /dev/null +++ b/examples/next_pinned.rs @@ -0,0 +1,13 @@ +use std::pin::pin; + +use event_iterator::EventIterator; + +#[async_main::async_main] +async fn main(_spawner: async_main::LocalSpawner) { + let mut ei = pin!(event_iterator::from_iter([3, 1, 2])); + + assert_eq!(Some(&3), ei.as_mut().next_pinned().await); + assert_eq!(Some(&1), ei.as_mut().next_pinned().await); + assert_eq!(Some(&2), ei.as_mut().next_pinned().await); + assert_eq!(None, ei.as_mut().next_pinned().await); +} diff --git a/examples/next_unpinned.rs b/examples/next_unpinned.rs deleted file mode 100644 index 4492f7f..0000000 --- a/examples/next_unpinned.rs +++ /dev/null @@ -1,11 +0,0 @@ -use event_iterator::EventIterator; - -#[async_main::async_main] -async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([3, 1, 2]); - - assert_eq!(Some(3), ei.next_unpinned().await); - assert_eq!(Some(1), ei.next_unpinned().await); - assert_eq!(Some(2), ei.next_unpinned().await); - assert_eq!(None, ei.next_unpinned().await); -} diff --git a/examples/size_hint.rs b/examples/size_hint.rs index 47821ca..3586f85 100644 --- a/examples/size_hint.rs +++ b/examples/size_hint.rs @@ -2,11 +2,11 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([1, 2, 3, 4, 5]); + let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]); assert_eq!((5, Some(5)), ei.size_hint()); - let _ = ei.next_unpinned().await; + let _ = ei.next().await; assert_eq!((4, Some(4)), ei.size_hint()); diff --git a/examples/take.rs b/examples/take.rs index c05c587..664f4d5 100644 --- a/examples/take.rs +++ b/examples/take.rs @@ -2,30 +2,31 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([1, 2, 3]).take(2); + let mut ei = event_iterator::from_iter([1, 2, 3]).take(2); - assert_eq!(ei.next_unpinned().await, Some(1)); - assert_eq!(ei.next_unpinned().await, Some(2)); - assert_eq!(ei.next_unpinned().await, None); - assert_eq!(ei.next_unpinned().await, None); + assert_eq!(ei.next().await, Some(&1)); + assert_eq!(ei.next().await, Some(&2)); + assert_eq!(ei.next().await, None); + assert_eq!(ei.next().await, None); - // `take()` is often used with an infinite iterator, to make it finite: + // `take()` is often used with an infinite event iterator, to make it + // finite: - let ei = event_iterator::from_iter(0..).take(3); + let mut ei = event_iterator::from_iter(0..).take(3); - assert_eq!(ei.next_unpinned().await, Some(0)); - assert_eq!(ei.next_unpinned().await, Some(1)); - assert_eq!(ei.next_unpinned().await, Some(2)); - assert_eq!(ei.next_unpinned().await, None); - assert_eq!(ei.next_unpinned().await, None); + assert_eq!(ei.next().await, Some(&0)); + assert_eq!(ei.next().await, Some(&1)); + assert_eq!(ei.next().await, Some(&2)); + assert_eq!(ei.next().await, None); + assert_eq!(ei.next().await, None); // If less than `n` elements are available, `take()` will limit itself to - // the size of the underlying iterator: + // the size of the underlying event iterator: - let ei = event_iterator::from_iter([1, 2]).take(5); + let mut ei = event_iterator::from_iter([1, 2]).take(5); - assert_eq!(ei.next_unpinned().await, Some(1)); - assert_eq!(ei.next_unpinned().await, Some(2)); - assert_eq!(ei.next_unpinned().await, None); - assert_eq!(ei.next_unpinned().await, None); + assert_eq!(ei.next().await, Some(&1)); + assert_eq!(ei.next().await, Some(&2)); + assert_eq!(ei.next().await, None); + assert_eq!(ei.next().await, None); } diff --git a/examples/tear.rs b/examples/tear.rs index b68b11a..34c3c6b 100644 --- a/examples/tear.rs +++ b/examples/tear.rs @@ -4,12 +4,12 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([1, 2, 3]).tear(); + let mut ei = event_iterator::from_iter([1, 2, 3]).tear(); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(Some(1))); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(Some(2))); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(Some(3))); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Ready(None)); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Pending); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Pending); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&1))); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&2))); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&3))); + assert_eq!(futures::poll!(ei.next()), Poll::Ready(None)); + assert_eq!(futures::poll!(ei.next()), Poll::Pending); + assert_eq!(futures::poll!(ei.next()), Poll::Pending); } diff --git a/src/event_iter.rs b/src/event_iter.rs index 84eed66..deb863a 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -31,8 +31,8 @@ pub trait EventIterator { where Self: 'me; - /// Attempt to pull out the next event of this event iterator, registering - /// the current task for wakeup if the event is not yet available. + /// Attempt to poll the next event of this event iterator, registering the + /// current task for wakeup if the event is not yet available. /// /// # Return value /// @@ -42,11 +42,8 @@ pub trait EventIterator { /// - `Poll::Pending` means that this event iterator’s next value is not /// ready yet. Implementations will ensure that the current task will be /// notified when the next value may be ready. - /// - `Poll::Ready(Some(val))` means that the event iterator has - /// successfully produced a value, `val`, and may produce further values - /// on subsequent poll_next calls. - /// - `Poll::Ready(None)` means that the event iterator has terminated, and - /// `poll_next()` should not be invoked again. + /// - `Poll::Ready(())` means that the event iterator is either ready to + /// lend an event or has terminated. `event()` should be called to check. /// /// # Panics /// @@ -68,46 +65,12 @@ pub trait EventIterator { /// Calling `event()` before `poll()` may panic, block forever or cause /// other kinds of problems; the `EventIterator` trait places no /// requirements on the effects of such a call. However, as the - /// `poll_next()` method is not marked unsafe, Rust’s usual rules apply: - /// calls must never cause undefined behavior (memory corruption, incorrect - /// use of unsafe functions, or the like), regardless of the event - /// iterator’s state. + /// `poll()` method is not marked unsafe, Rust’s usual rules apply: calls + /// must never cause undefined behavior (memory corruption, incorrect use of + /// unsafe functions, or the like), regardless of the event iterator’s + /// state. fn event<'a>(self: Pin<&'a mut Self>) -> Option>; - /// Create a future that resolves to the next event in the event iterator. - /// - /// This is more flexible than [`next_unpinned()`](Self::next_unpinned), but - /// often more verbose than needed. - /// - /// # Example - /// - /// ```rust - #[doc = include_str!("../examples/next.rs")] - /// ``` - fn next<'a>(self: Pin<&'a mut Self>) -> Next<'a, Self> - where - Self: Sized, - { - Next::new(self) - } - - /// Create a future that resolves to the next event in the event iterator. - /// - /// This is less flexible than [`next()`](Self::next), but avoids the need - /// to handle pinning yourself. - /// - /// # Example - /// - /// ```rust - #[doc = include_str!("../examples/next_unpinned.rs")] - /// ``` - fn next_unpinned(&mut self) -> Next<'_, Self> - where - Self: Sized + Unpin, - { - Pin::new(self).next() - } - /// Return the bounds on the remaining length of the event iterator. /// /// Specifically, `size_hint()` returns a tuple where the first element is @@ -144,6 +107,40 @@ pub trait EventIterator { (0, None) } + /// Create a future that resolves to the next event in the event iterator. + /// + /// This is less flexible than [`next()`](Self::next), but avoids the need + /// to handle pinning yourself. + /// + /// # Example + /// + /// ```rust + #[doc = include_str!("../examples/next.rs")] + /// ``` + fn next(&mut self) -> Next<'_, Self> + where + Self: Sized + Unpin, + { + Pin::new(self).next_pinned() + } + + /// Create a future that resolves to the next event in the event iterator. + /// + /// This is more flexible than [`next()`](Self::next), but often more + /// verbose than needed. + /// + /// # Example + /// + /// ```rust + #[doc = include_str!("../examples/next_pinned.rs")] + /// ``` + fn next_pinned<'a>(self: Pin<&'a mut Self>) -> Next<'a, Self> + where + Self: Sized, + { + Next::new(self) + } + /// Take a closure and create an event iterator which calls that closure on /// each event. /// diff --git a/src/from_iter.rs b/src/from_iter.rs index 0ce8ce8..825de6c 100644 --- a/src/from_iter.rs +++ b/src/from_iter.rs @@ -62,7 +62,13 @@ where } fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + let (lower, upper) = self.iter.size_hint(); + + if self.started { + (lower.saturating_sub(1), upper.map(|n| n.saturating_sub(1))) + } else { + (lower, upper) + } } } diff --git a/src/from_iter_mut.rs b/src/from_iter_mut.rs index e5f83e8..7afce25 100644 --- a/src/from_iter_mut.rs +++ b/src/from_iter_mut.rs @@ -62,7 +62,13 @@ where } fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() + let (lower, upper) = self.iter.size_hint(); + + if self.started { + (lower.saturating_sub(1), upper.map(|n| n.saturating_sub(1))) + } else { + (lower, upper) + } } } diff --git a/src/inspect.rs b/src/inspect.rs index 17503f0..0155ccf 100644 --- a/src/inspect.rs +++ b/src/inspect.rs @@ -45,9 +45,7 @@ where where I: 'me; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { - self.as_mut().event(); - + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { let mut this = self.project(); let poll = this.ei.as_mut().poll(cx); diff --git a/src/next.rs b/src/next.rs index 3f7b8eb..24ae443 100644 --- a/src/next.rs +++ b/src/next.rs @@ -9,7 +9,7 @@ use crate::EventIterator; /// Future to get the next event in an [`EventIterator`] /// /// This `struct` is created by the [`next()`](EventIterator::next) and -/// [`next_unpinned()`](EventIterator::next_unpinned) methods. See their +/// [`next_pinned()`](EventIterator::next_pinned) methods. See their /// documentation for more. #[derive(Debug)] pub struct Next<'a, Ei>(Option>); diff --git a/src/take.rs b/src/take.rs index 2eaafcf..f89a354 100644 --- a/src/take.rs +++ b/src/take.rs @@ -20,6 +20,8 @@ pin_project_lite::pin_project! { impl Take { pub(crate) fn new(ei: I, count: usize) -> Self { + let count = count.checked_add(1).expect("overflow in take"); + Self { ei, count } } } From 4c66e6e5c1307620a457d04c496d86d2f1174f0d Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Mon, 16 Dec 2024 23:01:41 -0600 Subject: [PATCH 04/16] Remove unnecessary `Unpin` bounds --- examples/map.rs | 4 +- examples/stdin.rs | 150 +++++++++++++++++++++---------------------- examples/stdout.rs | 50 +++++++-------- src/enumerate.rs | 2 +- src/filter.rs | 2 +- src/filter_map.rs | 2 +- src/from_iter.rs | 2 +- src/from_iter_mut.rs | 2 +- src/fuse.rs | 8 +-- src/inspect.rs | 2 +- src/take.rs | 2 +- src/take_while.rs | 2 +- src/tear.rs | 8 +-- 13 files changed, 113 insertions(+), 123 deletions(-) diff --git a/examples/map.rs b/examples/map.rs index e8bb2fb..adcb0a2 100644 --- a/examples/map.rs +++ b/examples/map.rs @@ -2,8 +2,8 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]) - .map(|&x| "uwu".repeat(x)); + let mut ei = + event_iterator::from_iter([1, 2, 3, 4, 5]).map(|&x| "uwu".repeat(x)); while let Some(i) = ei.next().await { println!("{i}"); diff --git a/examples/stdin.rs b/examples/stdin.rs index 046bb66..d1706d2 100644 --- a/examples/stdin.rs +++ b/examples/stdin.rs @@ -1,113 +1,111 @@ use std::{ - cell::Cell, future::Future, - io, mem, + io, pin::Pin, + sync::Arc, task::{Context, Poll}, - thread, + thread::{self, JoinHandle}, }; use event_iterator::EventIterator; use whisk::Channel; -/// An event iterator, for reading from stdin +/// An event iterator, for scanning from stdin #[derive(Default)] pub struct Stdin { - sender: Channel>, - recver: Cell>>>, - buffer: Cell>, - send: Cell + Send>>>>, + channel: Channel>>, + buffer: Option>, + join: Option>, } -impl EventIterator for Stdin { - type Event<'me> = Buffer<'me>; - - fn poll_next( - self: Pin<&Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); +impl Drop for Stdin { + fn drop(&mut self) { + self.join.take().unwrap().join().unwrap(); + } +} - if let Some(buffer) = this.buffer.take() { - let sender = this.sender.clone(); +impl Stdin { + pub fn new() -> Self { + let channel = Channel::new(); + let sender = channel.clone(); + let join = thread::spawn(move || { + pasts::Executor::default().block_on(async move { + let stdin = io::stdin(); + let mut buffer = String::new(); + let mut sending = Arc::new(String::new()); + + while stdin.read_line(&mut buffer).is_ok() { + let buf = if let Some(s) = Arc::get_mut(&mut sending) { + s + } else { + sending = Arc::new(String::new()); + Arc::get_mut(&mut sending).unwrap() + }; + + // Remove trailing newline + buffer.pop(); + + if buffer.is_empty() { + break; + } + + buf.replace_range(.., buffer.as_str()); + sender.send(Some(sending.clone())).await; + buffer.clear(); + } + + sender.send(None).await; + }) + }); - this.send.set(Some(Box::pin(async move { - sender.send(Some(buffer)).await - }))); + Self { + buffer: None, + join: Some(join), + channel, } + } +} - if let Some(mut future) = this.send.take() { - if future.as_mut().poll(cx).is_pending() { - this.send.set(Some(future)); - return Poll::Pending; - } - } +impl EventIterator for Stdin { + type Event<'me> = Buffer<'me>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let this = self.get_mut(); - let mut recver = this.recver.take().unwrap(); - let poll = match Pin::new(&mut recver).poll(cx) { - Poll::Ready(Some(buffer)) => { - this.buffer.set(Some(buffer)); - Poll::Ready(Some(Buffer(&this.buffer))) - } - Poll::Ready(None) => Poll::Ready(None), - Poll::Pending => Poll::Pending, + this.buffer = None; + + match Pin::new(&mut this.channel).poll(cx) { + Poll::Ready(Some(buffer)) => this.buffer = Some(buffer), + Poll::Ready(None) => {} + Poll::Pending => return Poll::Pending, }; - this.recver.set(Some(recver)); - poll + Poll::Ready(()) } -} -pub struct Buffer<'a>(&'a Cell>); + fn event(self: Pin<&mut Self>) -> Option> { + let this = self.get_mut(); -impl Buffer<'_> { - pub fn with(&self, f: impl FnOnce(&str)) { - self.0.set(self.0.take().map(|buf| { - f(&buf); - buf - })); + Some(Buffer(this.buffer.as_ref()?)) } } -async fn stdin_thread( - recver: Channel>, - sender: Channel>, -) { - let stdin = io::stdin(); - let mut buffer = String::new(); - - while stdin.read_line(&mut buffer).is_ok() { - // Remove trailing newline - buffer.pop(); +pub struct Buffer<'a>(&'a String); - if buffer.is_empty() { - break; - } - - sender.send(Some(mem::take(&mut buffer))).await; - buffer = recver.recv().await.unwrap_or_default(); - buffer.clear(); +impl Buffer<'_> { + pub fn with(&self, f: impl FnOnce(&str)) { + f(self.0) } - - sender.send(None).await; } #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - // Init stdin - let stdin = Stdin::default(); - let recver = stdin.sender.clone(); - let sender = Channel::new(); + println!("Echo example - enter empty line to quit"); - stdin.recver.set(Some(sender.clone())); - thread::spawn(move || { - pasts::Executor::default().block_on(stdin_thread(recver, sender)) - }); + let mut stdin = Stdin::new(); // Check messages - while let Some(buffer) = stdin.next_unpinned().await { - buffer.with(|message| { - println!("Echo: {message}"); - }); + while let Some(buffer) = stdin.next().await { + buffer.with(|message| println!("Echo: {message}")); } } diff --git a/examples/stdout.rs b/examples/stdout.rs index 89973de..ead109b 100644 --- a/examples/stdout.rs +++ b/examples/stdout.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, pin::{pin, Pin}, task::{Context, Poll}, }; @@ -9,53 +8,50 @@ use event_iterator::EventIterator; /// An event iterator, for printing to stdout #[derive(Default)] pub struct Stdout { - buffer: Cell>, + buffer: Option, } impl EventIterator for Stdout { type Event<'me> = Buffer<'me>; - fn poll_next( - self: Pin<&Self>, - _cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { + let this = self.get_mut(); - // Print last buffer contents if set, set if unset - this.buffer.set(if let Some(buffer) = this.buffer.take() { + if let Some(ref mut buffer) = this.buffer { // This could be an asynchronous operation // Left synchronous for example simplicity println!("{buffer}"); - // Reuse buffer - Some(buffer) + buffer.clear(); } else { - Some(String::new()) - }); - Poll::Ready(Some(Buffer(&this.buffer))) + this.buffer = Some(String::new()); + } + + Poll::Ready(()) + } + + fn event(self: Pin<&mut Self>) -> Option> { + let this = self.get_mut(); + + Some(Buffer(this.buffer.as_mut().unwrap())) } } -pub struct Buffer<'a>(&'a Cell>); +pub struct Buffer<'a>(&'a mut String); impl Buffer<'_> { - pub fn write(&self, text: &str) { - self.0.set(self.0.take().map(|mut buf| { - buf.replace_range(.., text); - buf - })); + pub fn write(&mut self, text: &str) { + self.0.replace_range(.., text); } } #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let stdout = Stdout::default(); + let mut stdout = Stdout::default(); // Overwrite buffer with text to print - stdout.next_unpinned().await.unwrap().write("Hello, world!"); - stdout.next_unpinned().await.unwrap().write("Hello, again!"); - - // Once more, to use the previous buffer contents - let flush = pin!(stdout); + stdout.next().await.unwrap().write("Hello, world!"); + stdout.next().await.unwrap().write("Hello, again!"); - flush.as_ref().next().await.unwrap(); + // Once more, to flush the previous buffer contents + pin!(stdout).next_pinned().await.unwrap(); } diff --git a/src/enumerate.rs b/src/enumerate.rs index 9ff238c..d215196 100644 --- a/src/enumerate.rs +++ b/src/enumerate.rs @@ -40,7 +40,7 @@ where impl EventIterator for Enumerate where - I: EventIterator + Unpin, + I: EventIterator, { type Event<'me> = (usize, I::Event<'me>) diff --git a/src/filter.rs b/src/filter.rs index b8b99eb..1b22a54 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -38,7 +38,7 @@ where impl EventIterator for Filter where - I: EventIterator + Unpin, + I: EventIterator, P: for<'me> FnMut(&I::Event<'me>) -> bool + 'static + Unpin, { type Event<'me> = I::Event<'me> where I: 'me; diff --git a/src/filter_map.rs b/src/filter_map.rs index df27d89..a004635 100644 --- a/src/filter_map.rs +++ b/src/filter_map.rs @@ -40,7 +40,7 @@ where impl EventIterator for FilterMap where - I: EventIterator + Unpin, + I: EventIterator, F: for<'me> FnMut(I::Event<'me>) -> Option + 'static + Unpin, { type Event<'me> = B where I: 'me; diff --git a/src/from_iter.rs b/src/from_iter.rs index 825de6c..54247aa 100644 --- a/src/from_iter.rs +++ b/src/from_iter.rs @@ -54,7 +54,7 @@ where fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let this = self.get_mut(); - if this.started == false { + if !this.started { panic!("{EVENT_BEFORE_POLL}"); } diff --git a/src/from_iter_mut.rs b/src/from_iter_mut.rs index 7afce25..7c9511e 100644 --- a/src/from_iter_mut.rs +++ b/src/from_iter_mut.rs @@ -54,7 +54,7 @@ where fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let this = self.get_mut(); - if this.started == false { + if !this.started { panic!("{EVENT_BEFORE_POLL}"); } diff --git a/src/fuse.rs b/src/fuse.rs index 8105f84..78e53c1 100644 --- a/src/fuse.rs +++ b/src/fuse.rs @@ -37,7 +37,7 @@ impl Fuse { impl EventIterator for Fuse where - I: EventIterator + Unpin, + I: EventIterator, { type Event<'me> = I::Event<'me> @@ -55,12 +55,10 @@ where fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let mut this = self.project(); - let Some(ei) = this.ei.as_mut().as_pin_mut() else { - return None; - }; + let ei = this.ei.as_mut().as_pin_mut()?; if ei.event().is_none() { - (*this.ei) = None; + this.ei.set(None); return None; } diff --git a/src/inspect.rs b/src/inspect.rs index 0155ccf..51def7b 100644 --- a/src/inspect.rs +++ b/src/inspect.rs @@ -37,7 +37,7 @@ where impl EventIterator for Inspect where - I: EventIterator + Unpin, + I: EventIterator, F: for<'me> FnMut(I::Event<'me>) + 'static, { type Event<'me> diff --git a/src/take.rs b/src/take.rs index f89a354..f45c3cf 100644 --- a/src/take.rs +++ b/src/take.rs @@ -40,7 +40,7 @@ where impl EventIterator for Take where - I: EventIterator + Unpin, + I: EventIterator, { type Event<'me> = I::Event<'me> diff --git a/src/take_while.rs b/src/take_while.rs index b1aba80..8f40f5f 100644 --- a/src/take_while.rs +++ b/src/take_while.rs @@ -38,7 +38,7 @@ where impl EventIterator for TakeWhile where - I: EventIterator + Unpin, + I: EventIterator, P: for<'me> FnMut(&I::Event<'me>) -> bool + 'static + Unpin, { type Event<'me> = I::Event<'me> where I: 'me; diff --git a/src/tear.rs b/src/tear.rs index 2528f3f..940a39d 100644 --- a/src/tear.rs +++ b/src/tear.rs @@ -36,7 +36,7 @@ impl Tear { impl EventIterator for Tear where - I: EventIterator + Unpin, + I: EventIterator, { type Event<'me> = I::Event<'me> @@ -54,12 +54,10 @@ where fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let mut this = self.project(); - let Some(ei) = this.ei.as_mut().as_pin_mut() else { - return None; - }; + let ei = this.ei.as_mut().as_pin_mut()?; if ei.event().is_none() { - (*this.ei) = None; + this.ei.set(None); return None; } From d8cc1258eb48929777d4b927f8b4194fbc13f7dd Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Tue, 17 Dec 2024 00:48:17 -0600 Subject: [PATCH 05/16] Fix all event iterator methods --- examples/filter.rs | 6 ++--- examples/filter_map.rs | 23 ++++++++--------- examples/take_while.rs | 11 ++++---- src/event_iter.rs | 16 +++++------- src/filter.rs | 37 ++++++++++++++------------- src/filter_map.rs | 55 +++++++++++++++++++++------------------ src/lib.rs | 12 ++++----- src/take_while.rs | 58 ++++++++++++++++++++++++------------------ 8 files changed, 114 insertions(+), 104 deletions(-) diff --git a/examples/filter.rs b/examples/filter.rs index 7e2e8d1..397f661 100644 --- a/examples/filter.rs +++ b/examples/filter.rs @@ -2,11 +2,11 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([1, 2, 3, 4, 5]).filter(|&x| x > 1); + let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]).filter(|&x| x > 1); let mut events = Vec::new(); - while let Some(event) = ei.next_unpinned().await { - events.push(event); + while let Some(event) = ei.next().await { + events.push(event.clone()); } println!("{events:?}"); diff --git a/examples/filter_map.rs b/examples/filter_map.rs index 3619eb2..bde717f 100644 --- a/examples/filter_map.rs +++ b/examples/filter_map.rs @@ -2,22 +2,21 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter(["1", "two", "NaN", "four", "5"]); - let ei = ei.filter_map(|s| s.parse().ok()); + let mut ei = event_iterator::from_iter(["1", "two", "NaN", "four", "5"]) + .filter_map(|s| s.parse().ok()); - assert_eq!(ei.next_unpinned().await, Some(1)); - assert_eq!(ei.next_unpinned().await, Some(5)); - assert_eq!(ei.next_unpinned().await, None); + assert_eq!(ei.next().await, Some(&1)); + assert_eq!(ei.next().await, Some(&5)); + assert_eq!(ei.next().await, None); // Here’s the same example, but with `filter()` and `map()`: - let ei = event_iterator::from_iter(["1", "two", "NaN", "four", "5"]); - let ei = ei - .map(|s| s.parse()) + let mut ei = event_iterator::from_iter(["1", "two", "NaN", "four", "5"]) + .map(|&s| s.parse()) .filter(|s| s.is_ok()) - .map(|s| s.unwrap()); + .map(|s| s.clone().unwrap()); - assert_eq!(ei.next_unpinned().await, Some(1)); - assert_eq!(ei.next_unpinned().await, Some(5)); - assert_eq!(ei.next_unpinned().await, None); + assert_eq!(ei.next().await, Some(&1)); + assert_eq!(ei.next().await, Some(&5)); + assert_eq!(ei.next().await, None); } diff --git a/examples/take_while.rs b/examples/take_while.rs index 0fed9ad..458d6ac 100644 --- a/examples/take_while.rs +++ b/examples/take_while.rs @@ -2,11 +2,12 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei = event_iterator::from_iter([-2i32, -1, 0, 1, -2]) + let mut ei = event_iterator::from_iter([-2i32, -1, 0, 1, -2]) .take_while(|x| x.is_negative()); - assert_eq!(ei.next_unpinned().await, Some(-2)); - assert_eq!(ei.next_unpinned().await, Some(-1)); - assert_eq!(ei.next_unpinned().await, None); - assert_eq!(ei.next_unpinned().await, None); + assert_eq!(ei.next().await, Some(&-2)); + assert_eq!(ei.next().await, Some(&-1)); + assert_eq!(ei.next().await, None); + assert_eq!(ei.next().await, None); + assert_eq!(ei.next().await, None); } diff --git a/src/event_iter.rs b/src/event_iter.rs index deb863a..4147ef3 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -5,8 +5,7 @@ use core::{ }; use crate::{ - Enumerate, /* Filter, FilterMap, */ Fuse, Inspect, Map, Next, - Take, /* TakeWhile, */ + Enumerate, Filter, FilterMap, Fuse, Inspect, Map, Next, Take, TakeWhile, Tear, }; @@ -182,7 +181,6 @@ pub trait EventIterator { Map::new(self, f) } - /* /// Create an event iterator which uses a closure to determine if an event /// should be yielded. /// @@ -198,7 +196,7 @@ pub trait EventIterator { fn filter

(self, predicate: P) -> Filter where Self: Sized, - P: for<'me> FnMut(&Self::Event<'me>) -> bool, + P: for<'me> FnMut(Self::Event<'me>) -> bool, { Filter::new(self, predicate) } @@ -218,13 +216,13 @@ pub trait EventIterator { /// ```rust #[doc = include_str!("../examples/filter_map.rs")] /// ``` - fn filter_map(self, f: F) -> FilterMap + fn filter_map(self, f: F) -> FilterMap where Self: Sized, - F: for<'me> FnMut(Self::Event<'me>) -> Option, + F: for<'me> FnMut(Self::Event<'me>) -> Option, { FilterMap::new(self, f) - }*/ + } /// Do something with each event of an event iterator, passing the value on. /// @@ -354,7 +352,6 @@ pub trait EventIterator { Take::new(self, n) } - /* /// Create an event iterator that yields elements based on a predicate. /// /// `take_while()` takes a closure as an argument. It will call this @@ -372,11 +369,10 @@ pub trait EventIterator { fn take_while

(self, predicate: P) -> TakeWhile where Self: Sized, - P: for<'me> FnMut(&Self::Event<'me>) -> bool, + P: for<'me> FnMut(Self::Event<'me>) -> bool, { TakeWhile::new(self, predicate) } - */ } impl EventIterator for T diff --git a/src/filter.rs b/src/filter.rs index 1b22a54..684c3f9 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -39,36 +39,37 @@ where impl EventIterator for Filter where I: EventIterator, - P: for<'me> FnMut(&I::Event<'me>) -> bool + 'static + Unpin, + P: for<'me> FnMut(I::Event<'me>) -> bool, { - type Event<'me> = I::Event<'me> where I: 'me; + type Event<'me> + = I::Event<'me> + where + I: 'me, + P: 'me; - fn poll_next<'a>( - self: Pin<&'a mut Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.get_ref(); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let mut this = self.project(); loop { - let Poll::Ready(event) = Pin::new(&this.ei).poll_next(cx) else { + let Poll::Ready(()) = this.ei.as_mut().poll(cx) else { break Poll::Pending; }; - let Some(event) = event else { - break Poll::Ready(None); + let Some(event) = this.ei.as_mut().event() else { + break Poll::Ready(()); }; - let Some(mut predicate) = this.p.take() else { - break Poll::Ready(None); - }; - let should_yield = predicate(&event); - - this.p.set(Some(predicate)); - if should_yield { - break Poll::Ready(Some(event)); + if (this.p)(event) { + break Poll::Ready(()); } } } + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + + this.ei.event() + } + fn size_hint(&self) -> (usize, Option) { let (_, upper) = self.ei.size_hint(); diff --git a/src/filter_map.rs b/src/filter_map.rs index a004635..f14117c 100644 --- a/src/filter_map.rs +++ b/src/filter_map.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, pin::Pin, task::{Context, Poll}, @@ -12,22 +11,23 @@ pin_project_lite::pin_project! { /// /// This `struct` is created by the [`EventIterator::filter_map()`] method. /// See its documentation for more. - pub struct FilterMap { + pub struct FilterMap { #[pin] ei: I, f: F, + event: Option, } } -impl FilterMap { +impl FilterMap { pub(crate) fn new(ei: I, f: F) -> Self { - let f = Cell::new(Some(f)); + let event = None; - Self { ei, f } + Self { ei, f, event } } } -impl fmt::Debug for FilterMap +impl fmt::Debug for FilterMap where I: fmt::Debug, { @@ -38,39 +38,44 @@ where } } -impl EventIterator for FilterMap +impl EventIterator for FilterMap where I: EventIterator, - F: for<'me> FnMut(I::Event<'me>) -> Option + 'static + Unpin, + F: for<'me> FnMut(I::Event<'me>) -> Option, { - type Event<'me> = B where I: 'me; + type Event<'me> + = &'me E + where + I: 'me, + E: 'me, + F: 'me; - fn poll_next<'a>( - self: Pin<&'a mut Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.project(); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let mut this = self.project(); loop { - let Poll::Ready(event) = Pin::new(&this.ei).poll_next(cx) else { + let Poll::Ready(()) = this.ei.as_mut().poll(cx) else { break Poll::Pending; }; - let Some(event) = event else { - break Poll::Ready(None); - }; - let Some(mut f) = this.f.take() else { - break Poll::Ready(None); + let Some(event) = this.ei.as_mut().event() else { + (*this.event) = None; + break Poll::Ready(()); }; - let event = f(event); - this.f.set(Some(f)); + (*this.event) = (this.f)(event); - let Some(event) = event else { continue }; - - break Poll::Ready(Some(event)); + if this.event.is_some() { + break Poll::Ready(()); + } } } + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + + this.event.as_ref() + } + fn size_hint(&self) -> (usize, Option) { let (_, upper) = self.ei.size_hint(); diff --git a/src/lib.rs b/src/lib.rs index 72fef1c..e271cf9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,8 +46,8 @@ //mod empty; mod enumerate; mod event_iter; -//mod filter; -//mod filter_map; +mod filter; +mod filter_map; //mod from_fn; mod consts; mod from_iter; @@ -64,7 +64,7 @@ mod next; //mod repeat; //mod repeat_with; mod take; -//mod take_while; +mod take_while; mod tear; pub use self::{ @@ -72,8 +72,8 @@ pub use self::{ // empty::{empty, Empty}, enumerate::Enumerate, event_iter::EventIterator, - // filter::Filter, - // filter_map::FilterMap, + filter::Filter, + filter_map::FilterMap, // from_fn::{from_fn, FromFn}, from_iter::{from_iter, FromIter}, from_iter_mut::{from_iter_mut, FromIterMut}, @@ -89,6 +89,6 @@ pub use self::{ // repeat::{repeat, Repeat}, // repeat_with::{repeat_with, RepeatWith}, take::Take, - // take_while::TakeWhile, + take_while::TakeWhile, tear::Tear, }; diff --git a/src/take_while.rs b/src/take_while.rs index 8f40f5f..5c88be2 100644 --- a/src/take_while.rs +++ b/src/take_while.rs @@ -14,13 +14,15 @@ pin_project_lite::pin_project! { /// See its documentation for more. pub struct TakeWhile { #[pin] - ei: I, + ei: Option, p: P, } } impl TakeWhile { pub(crate) fn new(ei: I, p: P) -> Self { + let ei = Some(ei); + Self { ei, p } } } @@ -39,37 +41,43 @@ where impl EventIterator for TakeWhile where I: EventIterator, - P: for<'me> FnMut(&I::Event<'me>) -> bool + 'static + Unpin, + P: for<'me> FnMut(I::Event<'me>) -> bool + 'static, { - type Event<'me> = I::Event<'me> where I: 'me; - - fn poll_next<'a>( - self: Pin<&'a mut Self>, - cx: &mut Context<'_>, - ) -> Poll>> { - let this = self.project(); + type Event<'me> + = I::Event<'me> + where + I: 'me; - loop { - let Poll::Ready(event) = Pin::new(&this.ei).poll_next(cx) else { - break Poll::Pending; - }; - let Some(event) = event else { - break Poll::Ready(None); - }; - let Some(mut predicate) = this.p.take() else { - break Poll::Ready(None); - }; - let should_yield = predicate(&event); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let mut this = self.project(); + let Some(mut ei) = this.ei.as_mut().as_pin_mut() else { + return Poll::Ready(()); + }; + let Poll::Ready(()) = ei.as_mut().poll(cx) else { + return Poll::Pending; + }; + let Some(event) = ei.as_mut().event() else { + return Poll::Ready(()); + }; - if should_yield { - this.p.set(Some(predicate)); - break Poll::Ready(Some(event)); - } + if !(this.p)(event) { + this.ei.set(None); } + + Poll::Ready(()) + } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + + this.ei.as_pin_mut()?.event() } fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.ei.size_hint(); + let Some(ref ei) = self.ei else { + return (0, None); + }; + let (_, upper) = ei.size_hint(); // Can't know a lower bound, due to the predicate (0, upper) From ce0ee9d8eeb40521606fb2f0132228772689bc0b Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Tue, 17 Dec 2024 00:49:56 -0600 Subject: [PATCH 06/16] Remove `'static` bounds --- src/inspect.rs | 5 +++-- src/take_while.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/inspect.rs b/src/inspect.rs index 51def7b..76787fd 100644 --- a/src/inspect.rs +++ b/src/inspect.rs @@ -38,12 +38,13 @@ where impl EventIterator for Inspect where I: EventIterator, - F: for<'me> FnMut(I::Event<'me>) + 'static, + F: for<'me> FnMut(I::Event<'me>), { type Event<'me> = I::Event<'me> where - I: 'me; + I: 'me, + F: 'me; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { let mut this = self.project(); diff --git a/src/take_while.rs b/src/take_while.rs index 5c88be2..43decef 100644 --- a/src/take_while.rs +++ b/src/take_while.rs @@ -41,12 +41,13 @@ where impl EventIterator for TakeWhile where I: EventIterator, - P: for<'me> FnMut(I::Event<'me>) -> bool + 'static, + P: for<'me> FnMut(I::Event<'me>) -> bool, { type Event<'me> = I::Event<'me> where - I: 'me; + I: 'me, + P: 'me; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { let mut this = self.project(); From c78672066befa3480da74c1eb809f516a71bd530 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Tue, 17 Dec 2024 23:28:43 -0600 Subject: [PATCH 07/16] Add `empty()` / `Empty` back --- examples/empty.rs | 6 +++--- examples/from_fn.rs | 14 +++++++------- src/empty.rs | 18 +++++++++++------- src/from_fn.rs | 34 +++++++++++++++++++++------------- src/from_iter.rs | 2 +- src/from_iter_mut.rs | 2 +- src/lib.rs | 6 +++--- 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/examples/empty.rs b/examples/empty.rs index b62a265..e080dd3 100644 --- a/examples/empty.rs +++ b/examples/empty.rs @@ -2,8 +2,8 @@ use event_iterator::{Empty, EventIterator}; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei: Empty = event_iterator::empty(); + let mut ei: Empty = event_iterator::empty(); - assert!(ei.next_unpinned().await.is_none()); - assert!(ei.next_unpinned().await.is_none()); + assert!(ei.next().await.is_none()); + assert!(ei.next().await.is_none()); } diff --git a/examples/from_fn.rs b/examples/from_fn.rs index d60c2fc..f327516 100644 --- a/examples/from_fn.rs +++ b/examples/from_fn.rs @@ -16,11 +16,11 @@ async fn main(_spawner: async_main::LocalSpawner) { }) }); - assert_eq!(ei.next_unpinned().await, Some(1)); - assert_eq!(ei.next_unpinned().await, Some(2)); - assert_eq!(ei.next_unpinned().await, Some(3)); - assert_eq!(ei.next_unpinned().await, Some(4)); - assert_eq!(ei.next_unpinned().await, Some(5)); - assert_eq!(ei.next_unpinned().await, None); - assert_eq!(ei.next_unpinned().await, None); + assert_eq!(ei.next().await, Some(1)); + assert_eq!(ei.next().await, Some(2)); + assert_eq!(ei.next().await, Some(3)); + assert_eq!(ei.next().await, Some(4)); + assert_eq!(ei.next().await, Some(5)); + assert_eq!(ei.next().await, None); + assert_eq!(ei.next().await, None); } diff --git a/src/empty.rs b/src/empty.rs index 2430fe4..2d89c76 100644 --- a/src/empty.rs +++ b/src/empty.rs @@ -7,7 +7,7 @@ use core::{ use crate::EventIterator; -/// Event iterator that yields nothing +/// [Fused](crate::Fuse) event iterator that yields nothing /// /// This event iterator is created by the [`empty()`] function. See its /// documentation for more. @@ -20,13 +20,17 @@ impl fmt::Debug for Empty { } impl EventIterator for Empty { - type Event<'me> = E where Self: 'me; + type Event<'me> + = E + where + Self: 'me; - fn poll_next<'a>( - self: Pin<&'a Self>, - _cx: &mut Context<'_>, - ) -> Poll>> { - Poll::Ready(None) + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { + Poll::Ready(()) + } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + None } fn size_hint(&self) -> (usize, Option) { diff --git a/src/from_fn.rs b/src/from_fn.rs index 9ceb05b..7bfabbf 100644 --- a/src/from_fn.rs +++ b/src/from_fn.rs @@ -1,5 +1,4 @@ use core::{ - cell::Cell, fmt, future::Future, pin::Pin, @@ -8,22 +7,30 @@ use core::{ use crate::EventIterator; -/// Event iterator where each iteration calls the provided closure -/// -/// This event iterator is created by the [`from_fn()`] function. See its -/// documentation for more. -pub struct FromFn { - generator: Cell>, - future: Cell>, +pin_project_lite::pin_project! { + /// Event iterator where each iteration calls the provided closure + /// + /// This event iterator is created by the [`from_fn()`] function. See its + /// documentation for more. + pub struct FromFn + where + F: Future, + G: FnMut() -> F, + { + generator: G, + #[pin] + future: Option, + event: Option, + } } -impl fmt::Debug for FromFn { +impl fmt::Debug for FromFn { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FromFn").finish_non_exhaustive() } } -impl EventIterator for FromFn +impl EventIterator for FromFn where F: Future> + Unpin, G: FnMut() -> F + Unpin, @@ -61,13 +68,14 @@ where /// ```rust #[doc = include_str!("../examples/from_fn.rs")] /// ``` -pub fn from_fn(gen: G) -> FromFn +pub fn from_fn(generator: G) -> FromFn where F: Future>, G: FnMut() -> F, { FromFn { - generator: Cell::new(Some(gen)), - future: Cell::new(None), + generator, + future: None, + event: None, } } diff --git a/src/from_iter.rs b/src/from_iter.rs index 54247aa..c53aff4 100644 --- a/src/from_iter.rs +++ b/src/from_iter.rs @@ -7,7 +7,7 @@ use core::{ use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; -/// Event iterator that was created from an iterator +/// Event iterator of references that was created from an iterator /// /// This event iterator is created by the [`from_iter()`] function. See its /// documentation for more. diff --git a/src/from_iter_mut.rs b/src/from_iter_mut.rs index 7c9511e..c1e7ca4 100644 --- a/src/from_iter_mut.rs +++ b/src/from_iter_mut.rs @@ -7,7 +7,7 @@ use core::{ use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; -/// Event iterator that was created from an iterator +/// Event iterator of exclusive references that was created from an iterator /// /// This event iterator is created by the [`from_iter_mut()`] function. See its /// documentation for more. diff --git a/src/lib.rs b/src/lib.rs index e271cf9..0c2c0f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ )] //mod as_event_iter; -//mod empty; +mod empty; mod enumerate; mod event_iter; mod filter; @@ -69,12 +69,12 @@ mod tear; pub use self::{ // as_event_iter::{AsEventIter, AsEventIterator}, - // empty::{empty, Empty}, + empty::{empty, Empty}, enumerate::Enumerate, event_iter::EventIterator, filter::Filter, filter_map::FilterMap, - // from_fn::{from_fn, FromFn}, + //from_fn::{from_fn, FromFn}, from_iter::{from_iter, FromIter}, from_iter_mut::{from_iter_mut, FromIterMut}, fuse::Fuse, From dfbeeed585098790745667263c6ebb1bf2734e67 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Tue, 17 Dec 2024 23:42:45 -0600 Subject: [PATCH 08/16] Rename `map()`/`Map` to `map_ref()`/`MapRef` --- examples/enumerate.rs | 2 +- examples/filter.rs | 3 +- examples/filter_map.rs | 16 ++++++----- examples/{from_iter.rs => from_iter_ref.rs} | 2 +- examples/fuse.rs | 2 +- examples/inspect.rs | 2 +- examples/{map.rs => map_ref.rs} | 4 +-- examples/next.rs | 2 +- examples/next_pinned.rs | 2 +- examples/size_hint.rs | 11 +++---- examples/take.rs | 6 ++-- examples/take_while.rs | 2 +- examples/tear.rs | 2 +- src/event_iter.rs | 32 ++++++++++----------- src/{from_iter.rs => from_iter_ref.rs} | 16 +++++------ src/lib.rs | 10 +++---- src/{map.rs => map_ref.rs} | 16 +++++------ 17 files changed, 67 insertions(+), 63 deletions(-) rename examples/{from_iter.rs => from_iter_ref.rs} (74%) rename examples/{map.rs => map_ref.rs} (64%) rename src/{from_iter.rs => from_iter_ref.rs} (81%) rename src/{map.rs => map_ref.rs} (74%) diff --git a/examples/enumerate.rs b/examples/enumerate.rs index 7840d08..dfb850c 100644 --- a/examples/enumerate.rs +++ b/examples/enumerate.rs @@ -2,7 +2,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter(['a', 'b', 'c']).enumerate(); + let mut ei = event_iterator::from_iter_ref(['a', 'b', 'c']).enumerate(); assert_eq!(ei.next().await, Some((0, &'a'))); assert_eq!(ei.next().await, Some((1, &'b'))); diff --git a/examples/filter.rs b/examples/filter.rs index 397f661..0bc60a1 100644 --- a/examples/filter.rs +++ b/examples/filter.rs @@ -2,7 +2,8 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]).filter(|&x| x > 1); + let mut ei = + event_iterator::from_iter_ref([1, 2, 3, 4, 5]).filter(|&x| x > 1); let mut events = Vec::new(); while let Some(event) = ei.next().await { diff --git a/examples/filter_map.rs b/examples/filter_map.rs index bde717f..d253732 100644 --- a/examples/filter_map.rs +++ b/examples/filter_map.rs @@ -2,19 +2,21 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter(["1", "two", "NaN", "four", "5"]) - .filter_map(|s| s.parse().ok()); + let mut ei = + event_iterator::from_iter_ref(["1", "two", "NaN", "four", "5"]) + .filter_map(|s| s.parse().ok()); assert_eq!(ei.next().await, Some(&1)); assert_eq!(ei.next().await, Some(&5)); assert_eq!(ei.next().await, None); - // Here’s the same example, but with `filter()` and `map()`: + // Here’s the same example, but with `filter()` and `map_ref()`: - let mut ei = event_iterator::from_iter(["1", "two", "NaN", "four", "5"]) - .map(|&s| s.parse()) - .filter(|s| s.is_ok()) - .map(|s| s.clone().unwrap()); + let mut ei = + event_iterator::from_iter_ref(["1", "two", "NaN", "four", "5"]) + .map_ref(|&s| s.parse()) + .filter(|s| s.is_ok()) + .map_ref(|s| s.clone().unwrap()); assert_eq!(ei.next().await, Some(&1)); assert_eq!(ei.next().await, Some(&5)); diff --git a/examples/from_iter.rs b/examples/from_iter_ref.rs similarity index 74% rename from examples/from_iter.rs rename to examples/from_iter_ref.rs index 2ccf42e..fe0e97b 100644 --- a/examples/from_iter.rs +++ b/examples/from_iter_ref.rs @@ -2,7 +2,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]); + let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]); while let Some(&i) = ei.next().await { println!("{i}"); diff --git a/examples/fuse.rs b/examples/fuse.rs index 7542f6b..4d9ba94 100644 --- a/examples/fuse.rs +++ b/examples/fuse.rs @@ -4,7 +4,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([1, 2, 3]).fuse(); + let mut ei = event_iterator::from_iter_ref([1, 2, 3]).fuse(); assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&1))); assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&2))); diff --git a/examples/inspect.rs b/examples/inspect.rs index ab4c95f..a8e1a7e 100644 --- a/examples/inspect.rs +++ b/examples/inspect.rs @@ -2,7 +2,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]).inspect(|&x| { + let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]).inspect(|&x| { let uwu = "uwu".repeat(x); println!("{uwu}"); diff --git a/examples/map.rs b/examples/map_ref.rs similarity index 64% rename from examples/map.rs rename to examples/map_ref.rs index adcb0a2..ba90f70 100644 --- a/examples/map.rs +++ b/examples/map_ref.rs @@ -2,8 +2,8 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = - event_iterator::from_iter([1, 2, 3, 4, 5]).map(|&x| "uwu".repeat(x)); + let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]) + .map_ref(|&x| "uwu".repeat(x)); while let Some(i) = ei.next().await { println!("{i}"); diff --git a/examples/next.rs b/examples/next.rs index 700edad..7ff5331 100644 --- a/examples/next.rs +++ b/examples/next.rs @@ -2,7 +2,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([3, 1, 2]); + let mut ei = event_iterator::from_iter_ref([3, 1, 2]); assert_eq!(Some(&3), ei.next().await); assert_eq!(Some(&1), ei.next().await); diff --git a/examples/next_pinned.rs b/examples/next_pinned.rs index 5f0e372..be072b1 100644 --- a/examples/next_pinned.rs +++ b/examples/next_pinned.rs @@ -4,7 +4,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = pin!(event_iterator::from_iter([3, 1, 2])); + let mut ei = pin!(event_iterator::from_iter_ref([3, 1, 2])); assert_eq!(Some(&3), ei.as_mut().next_pinned().await); assert_eq!(Some(&1), ei.as_mut().next_pinned().await); diff --git a/examples/size_hint.rs b/examples/size_hint.rs index 3586f85..e4bfb62 100644 --- a/examples/size_hint.rs +++ b/examples/size_hint.rs @@ -2,7 +2,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([1, 2, 3, 4, 5]); + let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]); assert_eq!((5, Some(5)), ei.size_hint()); @@ -15,15 +15,16 @@ async fn main(_spawner: async_main::LocalSpawner) { ///////////////////// // The even numbers in the range of zero to nine. - let iter = event_iterator::from_iter((0..10).filter(|x| x % 2 == 0)); + let iter = event_iterator::from_iter_ref((0..10).filter(|x| x % 2 == 0)); // We might iterate from zero to ten times. Knowing that it's five // exactly wouldn't be possible without executing filter(). assert_eq!((0, Some(10)), iter.size_hint()); // Let's add five more numbers with chain() - let iter = - event_iterator::from_iter((0..10).filter(|x| x % 2 == 0).chain(15..20)); + let iter = event_iterator::from_iter_ref( + (0..10).filter(|x| x % 2 == 0).chain(15..20), + ); // now both bounds are increased by five assert_eq!((5, Some(15)), iter.size_hint()); @@ -34,7 +35,7 @@ async fn main(_spawner: async_main::LocalSpawner) { // an infinite iterator has no upper bound // and the maximum possible lower bound - let iter = event_iterator::from_iter(0..); + let iter = event_iterator::from_iter_ref(0..); assert_eq!((usize::MAX, None), iter.size_hint()); } diff --git a/examples/take.rs b/examples/take.rs index 664f4d5..9ed194f 100644 --- a/examples/take.rs +++ b/examples/take.rs @@ -2,7 +2,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([1, 2, 3]).take(2); + let mut ei = event_iterator::from_iter_ref([1, 2, 3]).take(2); assert_eq!(ei.next().await, Some(&1)); assert_eq!(ei.next().await, Some(&2)); @@ -12,7 +12,7 @@ async fn main(_spawner: async_main::LocalSpawner) { // `take()` is often used with an infinite event iterator, to make it // finite: - let mut ei = event_iterator::from_iter(0..).take(3); + let mut ei = event_iterator::from_iter_ref(0..).take(3); assert_eq!(ei.next().await, Some(&0)); assert_eq!(ei.next().await, Some(&1)); @@ -23,7 +23,7 @@ async fn main(_spawner: async_main::LocalSpawner) { // If less than `n` elements are available, `take()` will limit itself to // the size of the underlying event iterator: - let mut ei = event_iterator::from_iter([1, 2]).take(5); + let mut ei = event_iterator::from_iter_ref([1, 2]).take(5); assert_eq!(ei.next().await, Some(&1)); assert_eq!(ei.next().await, Some(&2)); diff --git a/examples/take_while.rs b/examples/take_while.rs index 458d6ac..887b363 100644 --- a/examples/take_while.rs +++ b/examples/take_while.rs @@ -2,7 +2,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([-2i32, -1, 0, 1, -2]) + let mut ei = event_iterator::from_iter_ref([-2i32, -1, 0, 1, -2]) .take_while(|x| x.is_negative()); assert_eq!(ei.next().await, Some(&-2)); diff --git a/examples/tear.rs b/examples/tear.rs index 34c3c6b..9fd7ca1 100644 --- a/examples/tear.rs +++ b/examples/tear.rs @@ -4,7 +4,7 @@ use event_iterator::EventIterator; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter([1, 2, 3]).tear(); + let mut ei = event_iterator::from_iter_ref([1, 2, 3]).tear(); assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&1))); assert_eq!(futures::poll!(ei.next()), Poll::Ready(Some(&2))); diff --git a/src/event_iter.rs b/src/event_iter.rs index 4147ef3..219e9ed 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -5,7 +5,7 @@ use core::{ }; use crate::{ - Enumerate, Filter, FilterMap, Fuse, Inspect, Map, Next, Take, TakeWhile, + Enumerate, Filter, FilterMap, Fuse, Inspect, MapRef, Next, Take, TakeWhile, Tear, }; @@ -143,26 +143,26 @@ pub trait EventIterator { /// Take a closure and create an event iterator which calls that closure on /// each event. /// - /// `map()` transforms one event iterator into another, by means of its + /// `map_ref()` transforms one event iterator into another, by means of its /// argument: something that implements [`FnMut`]. It produces a new event /// iterator which calls this closure on each event of the original event /// iterator. /// - /// If you are good at thinking in types, you can think of `map()` like + /// If you are good at thinking in types, you can think of `map_ref()` like /// this: If you have an iterator that gives you elements of some type `A`, - /// and you want an iterator of some other type `B`, you can use `map()`, - /// passing a closure that takes an `A` and returns a `B`. + /// and you want an iterator of some other type `B`, you can use + /// `map_ref()`, passing a closure that takes an `A` and returns a `B`. /// - /// `map()` is conceptually similar to a `while let Some(_) = _.await` loop. - /// However, as `map()` is lazy, it is best used when you’re already working - /// with other event iterators. If you’re doing some sort of looping for a - /// side effect, it’s considered more idiomatic to use - /// `while let Some(_) = _.await` than `map()`. + /// `map_ref()` is conceptually similar to a `while let Some(_) = _.await` + /// loop. However, as `map_ref()` is lazy, it is best used when you’re + /// already working with other event iterators. If you’re doing some sort + /// of looping for a side effect, it’s considered more idiomatic to use + /// `while let Some(_) = _.await` than `map_ref()`. /// /// # Example /// /// ```rust - #[doc = include_str!("../examples/map.rs")] + #[doc = include_str!("../examples/map_ref.rs")] /// ``` /// /// Output: @@ -173,12 +173,12 @@ pub trait EventIterator { /// uwuuwuuwuuwu /// uwuuwuuwuuwuuwu /// ``` - fn map(self, f: F) -> Map + fn map_ref(self, f: F) -> MapRef where Self: Sized, F: for<'me> FnMut(Self::Event<'me>) -> E, { - Map::new(self, f) + MapRef::new(self, f) } /// Create an event iterator which uses a closure to determine if an event @@ -207,9 +207,9 @@ pub trait EventIterator { /// supplied closure returns `Some(event)`. /// /// `filter_map()` can be used to make chains of [`filter()`](Self::filter) - /// and [`map()`](Self::map) more concise. The example below shows how a - /// `map().filter().map()` can be shortened to a single call to - /// `filter_map()`. + /// and [`map_ref()`](Self::map_ref) more concise. The example below shows + /// how a `map_ref().filter().map_ref()` can be shortened to a single call + /// to `filter_map()`. /// /// # Example /// diff --git a/src/from_iter.rs b/src/from_iter_ref.rs similarity index 81% rename from src/from_iter.rs rename to src/from_iter_ref.rs index c53aff4..ccabdc6 100644 --- a/src/from_iter.rs +++ b/src/from_iter_ref.rs @@ -9,9 +9,9 @@ use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; /// Event iterator of references that was created from an iterator /// -/// This event iterator is created by the [`from_iter()`] function. See its +/// This event iterator is created by the [`from_iter_ref()`] function. See its /// documentation for more. -pub struct FromIter +pub struct FromIterRef where I: Iterator, { @@ -19,17 +19,17 @@ where started: bool, } -impl fmt::Debug for FromIter +impl fmt::Debug for FromIterRef where I: Iterator + fmt::Debug, ::Item: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("FromIter").field(&self.iter).finish() + f.debug_tuple("FromIterRef").field(&self.iter).finish() } } -impl EventIterator for FromIter +impl EventIterator for FromIterRef where I: Iterator + Unpin, ::Item: Unpin, @@ -77,7 +77,7 @@ where /// # Example /// /// ```rust -#[doc = include_str!("../examples/from_iter.rs")] +#[doc = include_str!("../examples/from_iter_ref.rs")] /// ``` /// /// Output: @@ -93,11 +93,11 @@ where /// /// The returned event iterator might panic if [`EventIterator::event()`] is /// called before [`EventIterator::poll()`]. -pub fn from_iter(iter: I) -> FromIter<::IntoIter> +pub fn from_iter_ref(iter: I) -> FromIterRef<::IntoIter> where I: IntoIterator, { - FromIter { + FromIterRef { iter: iter.into_iter().peekable(), started: false, } diff --git a/src/lib.rs b/src/lib.rs index 0c2c0f3..0b90f77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,11 +50,11 @@ mod filter; mod filter_map; //mod from_fn; mod consts; -mod from_iter; mod from_iter_mut; +mod from_iter_ref; mod fuse; mod inspect; -mod map; +mod map_ref; mod next; //mod once; //mod once_with; @@ -74,12 +74,12 @@ pub use self::{ event_iter::EventIterator, filter::Filter, filter_map::FilterMap, - //from_fn::{from_fn, FromFn}, - from_iter::{from_iter, FromIter}, from_iter_mut::{from_iter_mut, FromIterMut}, + //from_fn::{from_fn, FromFn}, + from_iter_ref::{from_iter_ref, FromIterRef}, fuse::Fuse, inspect::Inspect, - map::Map, + map_ref::MapRef, next::Next, // once::{once, Once}, // once_with::{once_with, OnceWith}, diff --git a/src/map.rs b/src/map_ref.rs similarity index 74% rename from src/map.rs rename to src/map_ref.rs index fc269de..6207be2 100644 --- a/src/map.rs +++ b/src/map_ref.rs @@ -7,11 +7,11 @@ use core::{ use crate::EventIterator; pin_project_lite::pin_project! { - /// Event iterator that maps the events with a closure + /// Event iterator that maps the events with a closure to a reference /// - /// This `struct` is created by the [`EventIterator::map()`] method. See - /// its documentation for more. - pub struct Map { + /// This `struct` is created by the [`EventIterator::map_ref()`] method. + /// See its documentation for more. + pub struct MapRef { #[pin] ei: I, f: F, @@ -19,7 +19,7 @@ pin_project_lite::pin_project! { } } -impl Map { +impl MapRef { pub(crate) fn new(ei: I, f: F) -> Self { let event = None; @@ -27,18 +27,18 @@ impl Map { } } -impl fmt::Debug for Map +impl fmt::Debug for MapRef where I: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Map") + f.debug_struct("MapRef") .field("ei", &self.ei) .finish_non_exhaustive() } } -impl EventIterator for Map +impl EventIterator for MapRef where I: EventIterator, F: for<'me> FnMut(I::Event<'me>) -> E, From ec315bd27dc6c3e7618d63daa2b48f75194163b6 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Tue, 17 Dec 2024 23:54:55 -0600 Subject: [PATCH 09/16] Add `map_mut()` / `MapMut` --- examples/map_mut.rs | 13 ++++++++ examples/map_ref.rs | 2 ++ src/event_iter.rs | 52 +++++++++++++++++++++++++++----- src/lib.rs | 2 ++ src/map_mut.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 examples/map_mut.rs create mode 100644 src/map_mut.rs diff --git a/examples/map_mut.rs b/examples/map_mut.rs new file mode 100644 index 0000000..5457826 --- /dev/null +++ b/examples/map_mut.rs @@ -0,0 +1,13 @@ +use event_iterator::EventIterator; + +#[async_main::async_main] +async fn main(_spawner: async_main::LocalSpawner) { + let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]) + .map_mut(|&x| "uwu".repeat(x)); + + while let Some(i) = ei.next().await { + let i: &mut String = i; + + println!("{i}"); + } +} diff --git a/examples/map_ref.rs b/examples/map_ref.rs index ba90f70..b7e70a8 100644 --- a/examples/map_ref.rs +++ b/examples/map_ref.rs @@ -6,6 +6,8 @@ async fn main(_spawner: async_main::LocalSpawner) { .map_ref(|&x| "uwu".repeat(x)); while let Some(i) = ei.next().await { + let i: &String = i; + println!("{i}"); } } diff --git a/src/event_iter.rs b/src/event_iter.rs index 219e9ed..018e57a 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -5,8 +5,8 @@ use core::{ }; use crate::{ - Enumerate, Filter, FilterMap, Fuse, Inspect, MapRef, Next, Take, TakeWhile, - Tear, + Enumerate, Filter, FilterMap, Fuse, Inspect, MapMut, MapRef, Next, Take, + TakeWhile, Tear, }; /// Asynchronous lending iterator @@ -35,9 +35,6 @@ pub trait EventIterator { /// /// # Return value /// - /// There are several possible return values, each indicating a distinct - /// event iterator state: - /// /// - `Poll::Pending` means that this event iterator’s next value is not /// ready yet. Implementations will ensure that the current task will be /// notified when the next value may be ready. @@ -140,8 +137,8 @@ pub trait EventIterator { Next::new(self) } - /// Take a closure and create an event iterator which calls that closure on - /// each event. + /// Take a closure and create an event iterator of references which calls + /// that closure on each event. /// /// `map_ref()` transforms one event iterator into another, by means of its /// argument: something that implements [`FnMut`]. It produces a new event @@ -181,6 +178,47 @@ pub trait EventIterator { MapRef::new(self, f) } + /// Take a closure and create an event iterator of exclusive references + /// which calls that closure on each event. + /// + /// `map_mut()` transforms one event iterator into another, by means of its + /// argument: something that implements [`FnMut`]. It produces a new event + /// iterator which calls this closure on each event of the original event + /// iterator. + /// + /// If you are good at thinking in types, you can think of `map_mut()` like + /// this: If you have an iterator that gives you elements of some type `A`, + /// and you want an iterator of some other type `B`, you can use + /// `map_mut()`, passing a closure that takes an `A` and returns a `B`. + /// + /// `map_mut()` is conceptually similar to a `while let Some(_) = _.await` + /// loop. However, as `map_mut()` is lazy, it is best used when you’re + /// already working with other event iterators. If you’re doing some sort + /// of looping for a side effect, it’s considered more idiomatic to use + /// `while let Some(_) = _.await` than `map_mut()`. + /// + /// # Example + /// + /// ```rust + #[doc = include_str!("../examples/map_mut.rs")] + /// ``` + /// + /// Output: + /// ```console + /// uwu + /// uwuuwu + /// uwuuwuuwu + /// uwuuwuuwuuwu + /// uwuuwuuwuuwuuwu + /// ``` + fn map_mut(self, f: F) -> MapMut + where + Self: Sized, + F: for<'me> FnMut(Self::Event<'me>) -> E, + { + MapMut::new(self, f) + } + /// Create an event iterator which uses a closure to determine if an event /// should be yielded. /// diff --git a/src/lib.rs b/src/lib.rs index 0b90f77..327d808 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,6 +54,7 @@ mod from_iter_mut; mod from_iter_ref; mod fuse; mod inspect; +mod map_mut; mod map_ref; mod next; //mod once; @@ -79,6 +80,7 @@ pub use self::{ from_iter_ref::{from_iter_ref, FromIterRef}, fuse::Fuse, inspect::Inspect, + map_mut::MapMut, map_ref::MapRef, next::Next, // once::{once, Once}, diff --git a/src/map_mut.rs b/src/map_mut.rs new file mode 100644 index 0000000..12e8834 --- /dev/null +++ b/src/map_mut.rs @@ -0,0 +1,72 @@ +use core::{ + fmt, + pin::Pin, + task::{Context, Poll}, +}; + +use crate::EventIterator; + +pin_project_lite::pin_project! { + /// Event iterator that maps the events with a closure to an exclusive + /// reference + /// + /// This `struct` is created by the [`EventIterator::map_mut()`] method. + /// See its documentation for more. + pub struct MapMut { + #[pin] + ei: I, + f: F, + event: Option, + } +} + +impl MapMut { + pub(crate) fn new(ei: I, f: F) -> Self { + let event = None; + + Self { ei, f, event } + } +} + +impl fmt::Debug for MapMut +where + I: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MapMut") + .field("ei", &self.ei) + .finish_non_exhaustive() + } +} + +impl EventIterator for MapMut +where + I: EventIterator, + F: for<'me> FnMut(I::Event<'me>) -> E, +{ + type Event<'me> + = &'me mut E + where + Self: 'me; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let mut this = self.project(); + let poll = this.ei.as_mut().poll(cx); + + if poll.is_ready() { + (*this.event) = this.ei.event().map(this.f); + } + + poll + } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + + this.event.as_mut() + } + + fn size_hint(&self) -> (usize, Option) { + self.ei.size_hint() + } +} From d1c34401f81f1fbcff23e4ff79ed8c022a77ca31 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Wed, 18 Dec 2024 00:07:10 -0600 Subject: [PATCH 10/16] Add back `pending` / `Pending` --- examples/pending.rs | 8 +++----- src/lib.rs | 4 ++-- src/pending.rs | 19 ++++++++++++------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/examples/pending.rs b/examples/pending.rs index 4caaf14..9bf81c2 100644 --- a/examples/pending.rs +++ b/examples/pending.rs @@ -1,11 +1,9 @@ -use std::task::Poll; - use event_iterator::{EventIterator, Pending}; #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let ei: Pending = event_iterator::pending(); + let mut ei: Pending = event_iterator::pending(); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Pending); - assert_eq!(futures::poll!(ei.next_unpinned()), Poll::Pending); + assert!(futures::poll!(ei.next()).is_pending()); + assert!(futures::poll!(ei.next()).is_pending()); } diff --git a/src/lib.rs b/src/lib.rs index 327d808..f8c6362 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,7 +59,7 @@ mod map_ref; mod next; //mod once; //mod once_with; -//mod pending; +mod pending; //mod poll_fn; //mod ready; //mod repeat; @@ -85,7 +85,7 @@ pub use self::{ next::Next, // once::{once, Once}, // once_with::{once_with, OnceWith}, - // pending::{pending, Pending}, + pending::{pending, Pending}, // poll_fn::{poll_fn, PollFn}, // ready::{ready, Ready}, // repeat::{repeat, Repeat}, diff --git a/src/pending.rs b/src/pending.rs index 26e89e6..4e6117b 100644 --- a/src/pending.rs +++ b/src/pending.rs @@ -5,9 +5,10 @@ use core::{ task::{Context, Poll}, }; -use crate::EventIterator; +use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; -/// Event iterator that never produces an event and never finishes +/// [Torn](crate::Tear) event iterator that never produces an event and never +/// finishes /// /// This event iterator is created by the [`pending()`] function. See its /// documentation for more. @@ -20,14 +21,18 @@ impl fmt::Debug for Pending { } impl EventIterator for Pending { - type Event<'me> = E where Self: 'me; + type Event<'me> + = E + where + Self: 'me; - fn poll_next<'a>( - self: Pin<&'a Self>, - _cx: &mut Context<'_>, - ) -> Poll>> { + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { Poll::Pending } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + panic!("{EVENT_BEFORE_POLL}"); + } } /// Create an event iterator that never produces an event and never finishes. From 0662dfa829036dfb5ca294a34ff7c055fba68599 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Wed, 18 Dec 2024 21:33:20 -0600 Subject: [PATCH 11/16] Split `filter_map()` to `*_mut` / `*_ref()` --- examples/filter_map_mut.rs | 24 ++++++ examples/{filter_map.rs => filter_map_ref.rs} | 2 +- src/event_iter.rs | 41 +++++++-- src/filter_map_mut.rs | 86 +++++++++++++++++++ src/{filter_map.rs => filter_map_ref.rs} | 17 ++-- src/lib.rs | 6 +- 6 files changed, 156 insertions(+), 20 deletions(-) create mode 100644 examples/filter_map_mut.rs rename examples/{filter_map.rs => filter_map_ref.rs} (93%) create mode 100644 src/filter_map_mut.rs rename src/{filter_map.rs => filter_map_ref.rs} (84%) diff --git a/examples/filter_map_mut.rs b/examples/filter_map_mut.rs new file mode 100644 index 0000000..5f5dcf8 --- /dev/null +++ b/examples/filter_map_mut.rs @@ -0,0 +1,24 @@ +use event_iterator::EventIterator; + +#[async_main::async_main] +async fn main(_spawner: async_main::LocalSpawner) { + let mut ei = + event_iterator::from_iter_ref(["1", "two", "NaN", "four", "5"]) + .filter_map_mut(|&s| s.parse().ok()); + + assert_eq!(ei.next().await, Some(&mut 1)); + assert_eq!(ei.next().await, Some(&mut 5)); + assert_eq!(ei.next().await, None); + + // Here’s the same example, but with `filter()` and `map_ref()`: + + let mut ei = + event_iterator::from_iter_ref(["1", "two", "NaN", "four", "5"]) + .map_mut(|&s| s.parse()) + .filter(|s| s.is_ok()) + .map_mut(|s| s.clone().unwrap()); + + assert_eq!(ei.next().await, Some(&mut 1)); + assert_eq!(ei.next().await, Some(&mut 5)); + assert_eq!(ei.next().await, None); +} diff --git a/examples/filter_map.rs b/examples/filter_map_ref.rs similarity index 93% rename from examples/filter_map.rs rename to examples/filter_map_ref.rs index d253732..a150447 100644 --- a/examples/filter_map.rs +++ b/examples/filter_map_ref.rs @@ -4,7 +4,7 @@ use event_iterator::EventIterator; async fn main(_spawner: async_main::LocalSpawner) { let mut ei = event_iterator::from_iter_ref(["1", "two", "NaN", "four", "5"]) - .filter_map(|s| s.parse().ok()); + .filter_map_ref(|&s| s.parse().ok()); assert_eq!(ei.next().await, Some(&1)); assert_eq!(ei.next().await, Some(&5)); diff --git a/src/event_iter.rs b/src/event_iter.rs index 018e57a..767dde8 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -5,8 +5,8 @@ use core::{ }; use crate::{ - Enumerate, Filter, FilterMap, Fuse, Inspect, MapMut, MapRef, Next, Take, - TakeWhile, Tear, + Enumerate, Filter, FilterMapMut, FilterMapRef, Fuse, Inspect, MapMut, + MapRef, Next, Take, TakeWhile, Tear, }; /// Asynchronous lending iterator @@ -244,22 +244,45 @@ pub trait EventIterator { /// The returned event iterator yields only the events for which the /// supplied closure returns `Some(event)`. /// - /// `filter_map()` can be used to make chains of [`filter()`](Self::filter) - /// and [`map_ref()`](Self::map_ref) more concise. The example below shows - /// how a `map_ref().filter().map_ref()` can be shortened to a single call - /// to `filter_map()`. + /// `filter_map_ref()` can be used to make chains of + /// [`filter()`](Self::filter) and [`map_ref()`](Self::map_ref) more + /// concise. The example below shows how a `map_ref().filter().map_ref()` + /// can be shortened to a single call to `filter_map_ref()`. /// /// # Example /// /// ```rust - #[doc = include_str!("../examples/filter_map.rs")] + #[doc = include_str!("../examples/filter_map_ref.rs")] /// ``` - fn filter_map(self, f: F) -> FilterMap + fn filter_map_ref(self, f: F) -> FilterMapRef where Self: Sized, F: for<'me> FnMut(Self::Event<'me>) -> Option, { - FilterMap::new(self, f) + FilterMapRef::new(self, f) + } + + /// Create an event iterator that both filters and maps. + /// + /// The returned event iterator yields only the events for which the + /// supplied closure returns `Some(event)`. + /// + /// `filter_map_mut()` can be used to make chains of + /// [`filter()`](Self::filter) and [`map_mut()`](Self::map_mut) more + /// concise. The example below shows how a `map_mut().filter().map_mut()` + /// can be shortened to a single call to `filter_map_mut()`. + /// + /// # Example + /// + /// ```rust + #[doc = include_str!("../examples/filter_map_ref.rs")] + /// ``` + fn filter_map_mut(self, f: F) -> FilterMapMut + where + Self: Sized, + F: for<'me> FnMut(Self::Event<'me>) -> Option, + { + FilterMapMut::new(self, f) } /// Do something with each event of an event iterator, passing the value on. diff --git a/src/filter_map_mut.rs b/src/filter_map_mut.rs new file mode 100644 index 0000000..34514f2 --- /dev/null +++ b/src/filter_map_mut.rs @@ -0,0 +1,86 @@ +use core::{ + fmt, + pin::Pin, + task::{Context, Poll}, +}; + +use crate::EventIterator; + +pin_project_lite::pin_project! { + /// Event iterator that uses a closure to both filter and map a reference to + /// events + /// + /// This `struct` is created by the [`EventIterator::filter_map_mut()`] + /// method. See its documentation for more. + pub struct FilterMapMut { + #[pin] + ei: I, + f: F, + event: Option, + } +} + +impl FilterMapMut { + pub(crate) fn new(ei: I, f: F) -> Self { + let event = None; + + Self { ei, f, event } + } +} + +impl fmt::Debug for FilterMapMut +where + I: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FilterMapMut") + .field("ei", &self.ei) + .finish_non_exhaustive() + } +} + +impl EventIterator for FilterMapMut +where + I: EventIterator, + F: for<'me> FnMut(I::Event<'me>) -> Option, +{ + type Event<'me> + = &'me mut E + where + I: 'me, + E: 'me, + F: 'me; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let mut this = self.project(); + + loop { + let Poll::Ready(()) = this.ei.as_mut().poll(cx) else { + break Poll::Pending; + }; + let Some(event) = this.ei.as_mut().event() else { + (*this.event) = None; + break Poll::Ready(()); + }; + + (*this.event) = (this.f)(event); + + if this.event.is_some() { + break Poll::Ready(()); + } + } + } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + + this.event.as_mut() + } + + fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.ei.size_hint(); + + // Can't know a lower bound, due to the predicate + (0, upper) + } +} diff --git a/src/filter_map.rs b/src/filter_map_ref.rs similarity index 84% rename from src/filter_map.rs rename to src/filter_map_ref.rs index f14117c..d6b74c8 100644 --- a/src/filter_map.rs +++ b/src/filter_map_ref.rs @@ -7,11 +7,12 @@ use core::{ use crate::EventIterator; pin_project_lite::pin_project! { - /// Event iterator that uses a closure to both filter and map events + /// Event iterator that uses a closure to both filter and map a reference to + /// events /// - /// This `struct` is created by the [`EventIterator::filter_map()`] method. - /// See its documentation for more. - pub struct FilterMap { + /// This `struct` is created by the [`EventIterator::filter_map_ref()`] + /// method. See its documentation for more. + pub struct FilterMapRef { #[pin] ei: I, f: F, @@ -19,7 +20,7 @@ pin_project_lite::pin_project! { } } -impl FilterMap { +impl FilterMapRef { pub(crate) fn new(ei: I, f: F) -> Self { let event = None; @@ -27,18 +28,18 @@ impl FilterMap { } } -impl fmt::Debug for FilterMap +impl fmt::Debug for FilterMapRef where I: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FilterMap") + f.debug_struct("FilterMapRef") .field("ei", &self.ei) .finish_non_exhaustive() } } -impl EventIterator for FilterMap +impl EventIterator for FilterMapRef where I: EventIterator, F: for<'me> FnMut(I::Event<'me>) -> Option, diff --git a/src/lib.rs b/src/lib.rs index f8c6362..ef5a9ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,7 +47,8 @@ mod empty; mod enumerate; mod event_iter; mod filter; -mod filter_map; +mod filter_map_mut; +mod filter_map_ref; //mod from_fn; mod consts; mod from_iter_mut; @@ -74,7 +75,8 @@ pub use self::{ enumerate::Enumerate, event_iter::EventIterator, filter::Filter, - filter_map::FilterMap, + filter_map_mut::FilterMapMut, + filter_map_ref::FilterMapRef, from_iter_mut::{from_iter_mut, FromIterMut}, //from_fn::{from_fn, FromFn}, from_iter_ref::{from_iter_ref, FromIterRef}, From e46314ddf8611689d4d4646d2cc2873a67a7cf88 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Wed, 18 Dec 2024 22:25:58 -0600 Subject: [PATCH 12/16] Fix doc link --- src/event_iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event_iter.rs b/src/event_iter.rs index 767dde8..2c342d6 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -275,7 +275,7 @@ pub trait EventIterator { /// # Example /// /// ```rust - #[doc = include_str!("../examples/filter_map_ref.rs")] + #[doc = include_str!("../examples/filter_map_mut.rs")] /// ``` fn filter_map_mut(self, f: F) -> FilterMapMut where From cd950f09aca3a1f2a728d89df64e2a34b7cdae2c Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Wed, 18 Dec 2024 23:56:37 -0600 Subject: [PATCH 13/16] Require `Copy` for `Event` --- examples/filter_map_mut.rs | 24 --------- examples/from_iter_mut.rs | 10 ---- examples/map_mut.rs | 13 ----- examples/stdin.rs | 1 + examples/stdout.rs | 13 +++-- src/empty.rs | 21 ++++++-- src/event_iter.rs | 70 ++----------------------- src/filter_map_mut.rs | 86 ------------------------------ src/from_iter_mut.rs | 104 ------------------------------------- src/lib.rs | 6 --- src/map_mut.rs | 72 ------------------------- src/pending.rs | 19 +++++-- 12 files changed, 44 insertions(+), 395 deletions(-) delete mode 100644 examples/filter_map_mut.rs delete mode 100644 examples/from_iter_mut.rs delete mode 100644 examples/map_mut.rs delete mode 100644 src/filter_map_mut.rs delete mode 100644 src/from_iter_mut.rs delete mode 100644 src/map_mut.rs diff --git a/examples/filter_map_mut.rs b/examples/filter_map_mut.rs deleted file mode 100644 index 5f5dcf8..0000000 --- a/examples/filter_map_mut.rs +++ /dev/null @@ -1,24 +0,0 @@ -use event_iterator::EventIterator; - -#[async_main::async_main] -async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = - event_iterator::from_iter_ref(["1", "two", "NaN", "four", "5"]) - .filter_map_mut(|&s| s.parse().ok()); - - assert_eq!(ei.next().await, Some(&mut 1)); - assert_eq!(ei.next().await, Some(&mut 5)); - assert_eq!(ei.next().await, None); - - // Here’s the same example, but with `filter()` and `map_ref()`: - - let mut ei = - event_iterator::from_iter_ref(["1", "two", "NaN", "four", "5"]) - .map_mut(|&s| s.parse()) - .filter(|s| s.is_ok()) - .map_mut(|s| s.clone().unwrap()); - - assert_eq!(ei.next().await, Some(&mut 1)); - assert_eq!(ei.next().await, Some(&mut 5)); - assert_eq!(ei.next().await, None); -} diff --git a/examples/from_iter_mut.rs b/examples/from_iter_mut.rs deleted file mode 100644 index 5bfa9cc..0000000 --- a/examples/from_iter_mut.rs +++ /dev/null @@ -1,10 +0,0 @@ -use event_iterator::EventIterator; - -#[async_main::async_main] -async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter_mut([1, 2, 3, 4, 5]); - - while let Some(&mut i) = ei.next().await { - println!("{i}"); - } -} diff --git a/examples/map_mut.rs b/examples/map_mut.rs deleted file mode 100644 index 5457826..0000000 --- a/examples/map_mut.rs +++ /dev/null @@ -1,13 +0,0 @@ -use event_iterator::EventIterator; - -#[async_main::async_main] -async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]) - .map_mut(|&x| "uwu".repeat(x)); - - while let Some(i) = ei.next().await { - let i: &mut String = i; - - println!("{i}"); - } -} diff --git a/examples/stdin.rs b/examples/stdin.rs index d1706d2..9fa3b64 100644 --- a/examples/stdin.rs +++ b/examples/stdin.rs @@ -90,6 +90,7 @@ impl EventIterator for Stdin { } } +#[derive(Copy, Clone)] pub struct Buffer<'a>(&'a String); impl Buffer<'_> { diff --git a/examples/stdout.rs b/examples/stdout.rs index ead109b..a0c7d2c 100644 --- a/examples/stdout.rs +++ b/examples/stdout.rs @@ -1,4 +1,5 @@ use core::{ + cell::Cell, pin::{pin, Pin}, task::{Context, Poll}, }; @@ -32,15 +33,19 @@ impl EventIterator for Stdout { fn event(self: Pin<&mut Self>) -> Option> { let this = self.get_mut(); - Some(Buffer(this.buffer.as_mut().unwrap())) + Some(Buffer(Cell::from_mut(this.buffer.as_mut().unwrap()))) } } -pub struct Buffer<'a>(&'a mut String); +#[derive(Copy, Clone)] +pub struct Buffer<'a>(&'a Cell); impl Buffer<'_> { - pub fn write(&mut self, text: &str) { - self.0.replace_range(.., text); + pub fn write(&self, text: &str) { + let mut buffer = self.0.take(); + + buffer.replace_range(.., text); + self.0.set(buffer); } } diff --git a/src/empty.rs b/src/empty.rs index 2d89c76..2cb51a0 100644 --- a/src/empty.rs +++ b/src/empty.rs @@ -11,15 +11,23 @@ use crate::EventIterator; /// /// This event iterator is created by the [`empty()`] function. See its /// documentation for more. -pub struct Empty(PhantomData); - -impl fmt::Debug for Empty { +pub struct Empty(PhantomData) +where + E: Copy; + +impl fmt::Debug for Empty +where + E: Copy, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Empty").field(&format_args!("_")).finish() } } -impl EventIterator for Empty { +impl EventIterator for Empty +where + E: Copy, +{ type Event<'me> = E where @@ -47,6 +55,9 @@ impl EventIterator for Empty { /// ```rust #[doc = include_str!("../examples/empty.rs")] /// ``` -pub fn empty() -> Empty { +pub fn empty() -> Empty +where + E: Copy, +{ Empty(PhantomData::) } diff --git a/src/event_iter.rs b/src/event_iter.rs index 2c342d6..faa1faa 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -5,8 +5,8 @@ use core::{ }; use crate::{ - Enumerate, Filter, FilterMapMut, FilterMapRef, Fuse, Inspect, MapMut, - MapRef, Next, Take, TakeWhile, Tear, + Enumerate, Filter, FilterMapRef, Fuse, Inspect, MapRef, Next, Take, + TakeWhile, Tear, }; /// Asynchronous lending iterator @@ -26,7 +26,7 @@ use crate::{ /// ``` pub trait EventIterator { /// The type of the events being iterated over - type Event<'me> + type Event<'me>: Copy where Self: 'me; @@ -178,47 +178,6 @@ pub trait EventIterator { MapRef::new(self, f) } - /// Take a closure and create an event iterator of exclusive references - /// which calls that closure on each event. - /// - /// `map_mut()` transforms one event iterator into another, by means of its - /// argument: something that implements [`FnMut`]. It produces a new event - /// iterator which calls this closure on each event of the original event - /// iterator. - /// - /// If you are good at thinking in types, you can think of `map_mut()` like - /// this: If you have an iterator that gives you elements of some type `A`, - /// and you want an iterator of some other type `B`, you can use - /// `map_mut()`, passing a closure that takes an `A` and returns a `B`. - /// - /// `map_mut()` is conceptually similar to a `while let Some(_) = _.await` - /// loop. However, as `map_mut()` is lazy, it is best used when you’re - /// already working with other event iterators. If you’re doing some sort - /// of looping for a side effect, it’s considered more idiomatic to use - /// `while let Some(_) = _.await` than `map_mut()`. - /// - /// # Example - /// - /// ```rust - #[doc = include_str!("../examples/map_mut.rs")] - /// ``` - /// - /// Output: - /// ```console - /// uwu - /// uwuuwu - /// uwuuwuuwu - /// uwuuwuuwuuwu - /// uwuuwuuwuuwuuwu - /// ``` - fn map_mut(self, f: F) -> MapMut - where - Self: Sized, - F: for<'me> FnMut(Self::Event<'me>) -> E, - { - MapMut::new(self, f) - } - /// Create an event iterator which uses a closure to determine if an event /// should be yielded. /// @@ -262,29 +221,6 @@ pub trait EventIterator { FilterMapRef::new(self, f) } - /// Create an event iterator that both filters and maps. - /// - /// The returned event iterator yields only the events for which the - /// supplied closure returns `Some(event)`. - /// - /// `filter_map_mut()` can be used to make chains of - /// [`filter()`](Self::filter) and [`map_mut()`](Self::map_mut) more - /// concise. The example below shows how a `map_mut().filter().map_mut()` - /// can be shortened to a single call to `filter_map_mut()`. - /// - /// # Example - /// - /// ```rust - #[doc = include_str!("../examples/filter_map_mut.rs")] - /// ``` - fn filter_map_mut(self, f: F) -> FilterMapMut - where - Self: Sized, - F: for<'me> FnMut(Self::Event<'me>) -> Option, - { - FilterMapMut::new(self, f) - } - /// Do something with each event of an event iterator, passing the value on. /// /// It’s more common for `inspect()` to be used as a debugging tool than to diff --git a/src/filter_map_mut.rs b/src/filter_map_mut.rs deleted file mode 100644 index 34514f2..0000000 --- a/src/filter_map_mut.rs +++ /dev/null @@ -1,86 +0,0 @@ -use core::{ - fmt, - pin::Pin, - task::{Context, Poll}, -}; - -use crate::EventIterator; - -pin_project_lite::pin_project! { - /// Event iterator that uses a closure to both filter and map a reference to - /// events - /// - /// This `struct` is created by the [`EventIterator::filter_map_mut()`] - /// method. See its documentation for more. - pub struct FilterMapMut { - #[pin] - ei: I, - f: F, - event: Option, - } -} - -impl FilterMapMut { - pub(crate) fn new(ei: I, f: F) -> Self { - let event = None; - - Self { ei, f, event } - } -} - -impl fmt::Debug for FilterMapMut -where - I: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FilterMapMut") - .field("ei", &self.ei) - .finish_non_exhaustive() - } -} - -impl EventIterator for FilterMapMut -where - I: EventIterator, - F: for<'me> FnMut(I::Event<'me>) -> Option, -{ - type Event<'me> - = &'me mut E - where - I: 'me, - E: 'me, - F: 'me; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { - let mut this = self.project(); - - loop { - let Poll::Ready(()) = this.ei.as_mut().poll(cx) else { - break Poll::Pending; - }; - let Some(event) = this.ei.as_mut().event() else { - (*this.event) = None; - break Poll::Ready(()); - }; - - (*this.event) = (this.f)(event); - - if this.event.is_some() { - break Poll::Ready(()); - } - } - } - - fn event<'a>(self: Pin<&'a mut Self>) -> Option> { - let this = self.project(); - - this.event.as_mut() - } - - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.ei.size_hint(); - - // Can't know a lower bound, due to the predicate - (0, upper) - } -} diff --git a/src/from_iter_mut.rs b/src/from_iter_mut.rs deleted file mode 100644 index c1e7ca4..0000000 --- a/src/from_iter_mut.rs +++ /dev/null @@ -1,104 +0,0 @@ -use core::{ - fmt, - iter::Peekable, - pin::Pin, - task::{Context, Poll}, -}; - -use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; - -/// Event iterator of exclusive references that was created from an iterator -/// -/// This event iterator is created by the [`from_iter_mut()`] function. See its -/// documentation for more. -pub struct FromIterMut -where - I: Iterator, -{ - iter: Peekable, - started: bool, -} - -impl fmt::Debug for FromIterMut -where - I: Iterator + fmt::Debug, - ::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("FromIterMut").field(&self.iter).finish() - } -} - -impl EventIterator for FromIterMut -where - I: Iterator + Unpin, - ::Item: Unpin, -{ - type Event<'me> - = &'me mut ::Item - where - I: 'me; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { - let this = self.get_mut(); - - if this.started { - _ = this.iter.next(); - } else { - this.started = true; - } - - Poll::Ready(()) - } - - fn event<'a>(self: Pin<&'a mut Self>) -> Option> { - let this = self.get_mut(); - - if !this.started { - panic!("{EVENT_BEFORE_POLL}"); - } - - this.iter.peek_mut() - } - - fn size_hint(&self) -> (usize, Option) { - let (lower, upper) = self.iter.size_hint(); - - if self.started { - (lower.saturating_sub(1), upper.map(|n| n.saturating_sub(1))) - } else { - (lower, upper) - } - } -} - -/// Convert an iterator into an event iterator of exclusive references. -/// -/// # Example -/// -/// ```rust -#[doc = include_str!("../examples/from_iter_mut.rs")] -/// ``` -/// -/// Output: -/// ```console -/// 1 -/// 2 -/// 3 -/// 4 -/// 5 -/// ``` -/// -/// # Panics -/// -/// The returned event iterator might panic if [`EventIterator::event()`] is -/// called before [`EventIterator::poll()`]. -pub fn from_iter_mut(iter: I) -> FromIterMut<::IntoIter> -where - I: IntoIterator, -{ - FromIterMut { - iter: iter.into_iter().peekable(), - started: false, - } -} diff --git a/src/lib.rs b/src/lib.rs index ef5a9ad..b3e2873 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,15 +47,12 @@ mod empty; mod enumerate; mod event_iter; mod filter; -mod filter_map_mut; mod filter_map_ref; //mod from_fn; mod consts; -mod from_iter_mut; mod from_iter_ref; mod fuse; mod inspect; -mod map_mut; mod map_ref; mod next; //mod once; @@ -75,14 +72,11 @@ pub use self::{ enumerate::Enumerate, event_iter::EventIterator, filter::Filter, - filter_map_mut::FilterMapMut, filter_map_ref::FilterMapRef, - from_iter_mut::{from_iter_mut, FromIterMut}, //from_fn::{from_fn, FromFn}, from_iter_ref::{from_iter_ref, FromIterRef}, fuse::Fuse, inspect::Inspect, - map_mut::MapMut, map_ref::MapRef, next::Next, // once::{once, Once}, diff --git a/src/map_mut.rs b/src/map_mut.rs deleted file mode 100644 index 12e8834..0000000 --- a/src/map_mut.rs +++ /dev/null @@ -1,72 +0,0 @@ -use core::{ - fmt, - pin::Pin, - task::{Context, Poll}, -}; - -use crate::EventIterator; - -pin_project_lite::pin_project! { - /// Event iterator that maps the events with a closure to an exclusive - /// reference - /// - /// This `struct` is created by the [`EventIterator::map_mut()`] method. - /// See its documentation for more. - pub struct MapMut { - #[pin] - ei: I, - f: F, - event: Option, - } -} - -impl MapMut { - pub(crate) fn new(ei: I, f: F) -> Self { - let event = None; - - Self { ei, f, event } - } -} - -impl fmt::Debug for MapMut -where - I: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MapMut") - .field("ei", &self.ei) - .finish_non_exhaustive() - } -} - -impl EventIterator for MapMut -where - I: EventIterator, - F: for<'me> FnMut(I::Event<'me>) -> E, -{ - type Event<'me> - = &'me mut E - where - Self: 'me; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { - let mut this = self.project(); - let poll = this.ei.as_mut().poll(cx); - - if poll.is_ready() { - (*this.event) = this.ei.event().map(this.f); - } - - poll - } - - fn event<'a>(self: Pin<&'a mut Self>) -> Option> { - let this = self.project(); - - this.event.as_mut() - } - - fn size_hint(&self) -> (usize, Option) { - self.ei.size_hint() - } -} diff --git a/src/pending.rs b/src/pending.rs index 4e6117b..51671e2 100644 --- a/src/pending.rs +++ b/src/pending.rs @@ -12,15 +12,23 @@ use crate::{consts::EVENT_BEFORE_POLL, EventIterator}; /// /// This event iterator is created by the [`pending()`] function. See its /// documentation for more. -pub struct Pending(PhantomData); +pub struct Pending(PhantomData) +where + E: Copy; -impl fmt::Debug for Pending { +impl fmt::Debug for Pending +where + E: Copy, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Pending").field(&format_args!("_")).finish() } } -impl EventIterator for Pending { +impl EventIterator for Pending +where + E: Copy, +{ type Event<'me> = E where @@ -44,6 +52,9 @@ impl EventIterator for Pending { /// ```rust #[doc = include_str!("../examples/pending.rs")] /// ``` -pub fn pending() -> Pending { +pub fn pending() -> Pending +where + E: Copy, +{ Pending(PhantomData::) } From 6ec64a098a1068e8befe64ea56dbaf9e842fefda Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Sun, 29 Dec 2024 21:47:19 -0600 Subject: [PATCH 14/16] Add `Map`/`map()` --- examples/map.rs | 25 ++++++++++++++++ src/event_iter.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 4 ++- src/map.rs | 64 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 examples/map.rs create mode 100644 src/map.rs diff --git a/examples/map.rs b/examples/map.rs new file mode 100644 index 0000000..0574a3a --- /dev/null +++ b/examples/map.rs @@ -0,0 +1,25 @@ +use event_iterator::{EventIterator, Lend}; + +#[derive(Copy, Clone)] +struct Uwu<'a>(&'a i32); + +#[derive(Copy, Clone)] +struct LendToUwu; + +impl Lend for LendToUwu { + type From<'a> = &'a i32; + type Into<'a> = Uwu<'a>; + + fn lend<'a>(self, from: Self::From<'a>) -> Self::Into<'a> { + Uwu(from) + } +} + +#[async_main::async_main] +async fn main(_spawner: async_main::LocalSpawner) { + let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]).map(LendToUwu); + + while let Some(Uwu(i)) = ei.next().await { + println!("{i}"); + } +} diff --git a/src/event_iter.rs b/src/event_iter.rs index faa1faa..fde8ccf 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -5,10 +5,39 @@ use core::{ }; use crate::{ - Enumerate, Filter, FilterMapRef, Fuse, Inspect, MapRef, Next, Take, + Enumerate, Filter, FilterMapRef, Fuse, Inspect, Map, MapRef, Next, Take, TakeWhile, Tear, }; +/// A lending conversion trait +pub trait Lend { + /// Type converting from + type From<'a>; + /// Type converting into + type Into<'a>; + + /// Lend a type to another type. + fn lend<'a>(self, from: Self::From<'a>) -> Self::Into<'a>; +} + +/* +impl Lend for T +where + T: Copy, +{ + type Event<'me> + = T + where + T: 'me; + + fn lend<'a>(self) -> Self::Event<'a> + where + T: 'a, + { + self + } +}*/ + /// Asynchronous lending iterator /// /// Rather than have a single `poll_next()` method as in `Stream` / @@ -137,6 +166,47 @@ pub trait EventIterator { Next::new(self) } + /// Take a closure and create an event iterator which calls that closure on + /// each event. + /// + /// `map_ref()` transforms one event iterator into another, by means of its + /// argument: something that implements [`FnMut`]. It produces a new event + /// iterator which calls this closure on each event of the original event + /// iterator. + /// + /// If you are good at thinking in types, you can think of `map_ref()` like + /// this: If you have an iterator that gives you elements of some type `A`, + /// and you want an iterator of some other type `B`, you can use + /// `map_ref()`, passing a closure that takes an `A` and returns a `B`. + /// + /// `map_ref()` is conceptually similar to a `while let Some(_) = _.await` + /// loop. However, as `map_ref()` is lazy, it is best used when you’re + /// already working with other event iterators. If you’re doing some sort + /// of looping for a side effect, it’s considered more idiomatic to use + /// `while let Some(_) = _.await` than `map_ref()`. + /// + /// # Example + /// + /// ```rust + #[doc = include_str!("../examples/map.rs")] + /// ``` + /// + /// Output: + /// ```console + /// uwu + /// uwuuwu + /// uwuuwuuwu + /// uwuuwuuwuuwu + /// uwuuwuuwuuwuuwu + /// ``` + fn map(self, lend: L) -> Map + where + Self: Sized, + L: for<'me> Lend = Self::Event<'me>> + Copy, + { + Map::new(self, lend) + } + /// Take a closure and create an event iterator of references which calls /// that closure on each event. /// diff --git a/src/lib.rs b/src/lib.rs index b3e2873..e0389cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,7 @@ mod consts; mod from_iter_ref; mod fuse; mod inspect; +mod map; mod map_ref; mod next; //mod once; @@ -70,13 +71,14 @@ pub use self::{ // as_event_iter::{AsEventIter, AsEventIterator}, empty::{empty, Empty}, enumerate::Enumerate, - event_iter::EventIterator, + event_iter::{EventIterator, Lend}, filter::Filter, filter_map_ref::FilterMapRef, //from_fn::{from_fn, FromFn}, from_iter_ref::{from_iter_ref, FromIterRef}, fuse::Fuse, inspect::Inspect, + map::Map, map_ref::MapRef, next::Next, // once::{once, Once}, diff --git a/src/map.rs b/src/map.rs new file mode 100644 index 0000000..d10f53d --- /dev/null +++ b/src/map.rs @@ -0,0 +1,64 @@ +use core::{ + fmt, + pin::Pin, + task::{Context, Poll}, +}; + +use crate::{EventIterator, Lend}; + +pin_project_lite::pin_project! { + /// Event iterator that maps the events with a closure + /// + /// This `struct` is created by the [`EventIterator::map()`] method. + /// See its documentation for more. + pub struct Map { + #[pin] + ei: I, + lend: L, + } +} + +impl Map { + pub(crate) fn new(ei: I, lend: L) -> Self { + Self { ei, lend } + } +} + +impl fmt::Debug for Map +where + I: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Map") + .field("ei", &self.ei) + .finish_non_exhaustive() + } +} + +impl EventIterator for Map +where + I: EventIterator, + L: for<'me> Lend = I::Event<'me>> + Copy, + for<'a> L::Into<'a>: Copy, +{ + type Event<'me> + = L::Into<'me> + where + Self: 'me; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let mut this = self.project(); + + this.ei.as_mut().poll(cx) + } + + fn event<'a>(self: Pin<&'a mut Self>) -> Option> { + let this = self.project(); + + Some(this.lend.lend(this.ei.event()?)) + } + + fn size_hint(&self) -> (usize, Option) { + self.ei.size_hint() + } +} From f472308173b2f2caaf63bce0640bd8f02164b6a2 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Sun, 29 Dec 2024 22:10:42 -0600 Subject: [PATCH 15/16] Rename `Lend` to `LendAs` --- examples/map.rs | 10 +++++----- src/event_iter.rs | 14 ++++++++------ src/lib.rs | 2 +- src/map.rs | 12 ++++++------ 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/examples/map.rs b/examples/map.rs index 0574a3a..e840f5f 100644 --- a/examples/map.rs +++ b/examples/map.rs @@ -1,23 +1,23 @@ -use event_iterator::{EventIterator, Lend}; +use event_iterator::{EventIterator, LendAs}; #[derive(Copy, Clone)] struct Uwu<'a>(&'a i32); #[derive(Copy, Clone)] -struct LendToUwu; +struct LendAsUwu; -impl Lend for LendToUwu { +impl LendAs for LendAsUwu { type From<'a> = &'a i32; type Into<'a> = Uwu<'a>; - fn lend<'a>(self, from: Self::From<'a>) -> Self::Into<'a> { + fn lend_as<'a>(self, from: Self::From<'a>) -> Self::Into<'a> { Uwu(from) } } #[async_main::async_main] async fn main(_spawner: async_main::LocalSpawner) { - let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]).map(LendToUwu); + let mut ei = event_iterator::from_iter_ref([1, 2, 3, 4, 5]).map(LendAsUwu); while let Some(Uwu(i)) = ei.next().await { println!("{i}"); diff --git a/src/event_iter.rs b/src/event_iter.rs index fde8ccf..6c411eb 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -10,14 +10,16 @@ use crate::{ }; /// A lending conversion trait -pub trait Lend { +/// +/// For lending a type as another. +pub trait LendAs { /// Type converting from type From<'a>; /// Type converting into type Into<'a>; /// Lend a type to another type. - fn lend<'a>(self, from: Self::From<'a>) -> Self::Into<'a>; + fn lend_as<'a>(self, from: Self::From<'a>) -> Self::Into<'a>; } /* @@ -190,7 +192,7 @@ pub trait EventIterator { /// ```rust #[doc = include_str!("../examples/map.rs")] /// ``` - /// + /// /// Output: /// ```console /// uwu @@ -199,12 +201,12 @@ pub trait EventIterator { /// uwuuwuuwuuwu /// uwuuwuuwuuwuuwu /// ``` - fn map(self, lend: L) -> Map + fn map(self, lend_as: L) -> Map where Self: Sized, - L: for<'me> Lend = Self::Event<'me>> + Copy, + L: for<'me> LendAs = Self::Event<'me>> + Copy, { - Map::new(self, lend) + Map::new(self, lend_as) } /// Take a closure and create an event iterator of references which calls diff --git a/src/lib.rs b/src/lib.rs index e0389cf..6702663 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,7 +71,7 @@ pub use self::{ // as_event_iter::{AsEventIter, AsEventIterator}, empty::{empty, Empty}, enumerate::Enumerate, - event_iter::{EventIterator, Lend}, + event_iter::{EventIterator, LendAs}, filter::Filter, filter_map_ref::FilterMapRef, //from_fn::{from_fn, FromFn}, diff --git a/src/map.rs b/src/map.rs index d10f53d..17ea8c3 100644 --- a/src/map.rs +++ b/src/map.rs @@ -4,7 +4,7 @@ use core::{ task::{Context, Poll}, }; -use crate::{EventIterator, Lend}; +use crate::{EventIterator, LendAs}; pin_project_lite::pin_project! { /// Event iterator that maps the events with a closure @@ -14,13 +14,13 @@ pin_project_lite::pin_project! { pub struct Map { #[pin] ei: I, - lend: L, + lend_as : L, } } impl Map { - pub(crate) fn new(ei: I, lend: L) -> Self { - Self { ei, lend } + pub(crate) fn new(ei: I, lend_as: L) -> Self { + Self { ei, lend_as } } } @@ -38,7 +38,7 @@ where impl EventIterator for Map where I: EventIterator, - L: for<'me> Lend = I::Event<'me>> + Copy, + L: for<'me> LendAs = I::Event<'me>> + Copy, for<'a> L::Into<'a>: Copy, { type Event<'me> @@ -55,7 +55,7 @@ where fn event<'a>(self: Pin<&'a mut Self>) -> Option> { let this = self.project(); - Some(this.lend.lend(this.ei.event()?)) + Some(this.lend_as.lend_as(this.ei.event()?)) } fn size_hint(&self) -> (usize, Option) { From 9a8275f9d4b32f7a9f1657f71737569442fd1512 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Tue, 14 Jan 2025 22:59:53 -0600 Subject: [PATCH 16/16] Move `LendAs` to own file --- src/event_iter.rs | 39 ++++----------------------------------- src/lend_as.rs | 12 ++++++++++++ src/lib.rs | 4 +++- src/map.rs | 2 +- 4 files changed, 20 insertions(+), 37 deletions(-) create mode 100644 src/lend_as.rs diff --git a/src/event_iter.rs b/src/event_iter.rs index 6c411eb..152c525 100644 --- a/src/event_iter.rs +++ b/src/event_iter.rs @@ -5,41 +5,10 @@ use core::{ }; use crate::{ - Enumerate, Filter, FilterMapRef, Fuse, Inspect, Map, MapRef, Next, Take, - TakeWhile, Tear, + Enumerate, Filter, FilterMapRef, Fuse, Inspect, LendAs, Map, MapRef, Next, + Take, TakeWhile, Tear, }; -/// A lending conversion trait -/// -/// For lending a type as another. -pub trait LendAs { - /// Type converting from - type From<'a>; - /// Type converting into - type Into<'a>; - - /// Lend a type to another type. - fn lend_as<'a>(self, from: Self::From<'a>) -> Self::Into<'a>; -} - -/* -impl Lend for T -where - T: Copy, -{ - type Event<'me> - = T - where - T: 'me; - - fn lend<'a>(self) -> Self::Event<'a> - where - T: 'a, - { - self - } -}*/ - /// Asynchronous lending iterator /// /// Rather than have a single `poll_next()` method as in `Stream` / @@ -168,8 +137,8 @@ pub trait EventIterator { Next::new(self) } - /// Take a closure and create an event iterator which calls that closure on - /// each event. + /// Take a type implementing [`LendAs`] and create an event iterator which + /// lends as a new type on each event. /// /// `map_ref()` transforms one event iterator into another, by means of its /// argument: something that implements [`FnMut`]. It produces a new event diff --git a/src/lend_as.rs b/src/lend_as.rs new file mode 100644 index 0000000..d41e8c8 --- /dev/null +++ b/src/lend_as.rs @@ -0,0 +1,12 @@ +/// A lending conversion trait +/// +/// For lending a type as another. Should be a lightweight operation. +pub trait LendAs { + /// Type converting from + type From<'a>; + /// Type converting into + type Into<'a>; + + /// Lend a type to another type. + fn lend_as(self, from: Self::From<'_>) -> Self::Into<'_>; +} diff --git a/src/lib.rs b/src/lib.rs index 6702663..b094cd2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,6 +63,7 @@ mod pending; //mod ready; //mod repeat; //mod repeat_with; +mod lend_as; mod take; mod take_while; mod tear; @@ -71,13 +72,14 @@ pub use self::{ // as_event_iter::{AsEventIter, AsEventIterator}, empty::{empty, Empty}, enumerate::Enumerate, - event_iter::{EventIterator, LendAs}, + event_iter::EventIterator, filter::Filter, filter_map_ref::FilterMapRef, //from_fn::{from_fn, FromFn}, from_iter_ref::{from_iter_ref, FromIterRef}, fuse::Fuse, inspect::Inspect, + lend_as::LendAs, map::Map, map_ref::MapRef, next::Next, diff --git a/src/map.rs b/src/map.rs index 17ea8c3..6926700 100644 --- a/src/map.rs +++ b/src/map.rs @@ -7,7 +7,7 @@ use core::{ use crate::{EventIterator, LendAs}; pin_project_lite::pin_project! { - /// Event iterator that maps the events with a closure + /// Event iterator that maps the events with a type implementing [`LendAs`] /// /// This `struct` is created by the [`EventIterator::map()`] method. /// See its documentation for more.