Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New design for EventIterator #2

Draft
wants to merge 16 commits into
base: v0
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rename next() / next_unpinned() to next_pinned() / next()
AldaronLau committed Dec 17, 2024
commit 21b31a40e4e23bca94cf3a80250512b5a7427a3d
8 changes: 4 additions & 4 deletions examples/enumerate.rs
Original file line number Diff line number Diff line change
@@ -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);
}
4 changes: 2 additions & 2 deletions examples/from_iter.rs
Original file line number Diff line number Diff line change
@@ -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}");
}
}
2 changes: 1 addition & 1 deletion examples/from_iter_mut.rs
Original file line number Diff line number Diff line change
@@ -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}");
}
}
12 changes: 6 additions & 6 deletions examples/fuse.rs
Original file line number Diff line number Diff line change
@@ -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));
}
4 changes: 2 additions & 2 deletions examples/inspect.rs
Original file line number Diff line number Diff line change
@@ -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() {}
}
4 changes: 2 additions & 2 deletions examples/map.rs
Original file line number Diff line number Diff line change
@@ -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}");
}
}
12 changes: 5 additions & 7 deletions examples/next.rs
Original file line number Diff line number Diff line change
@@ -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);
}
13 changes: 13 additions & 0 deletions examples/next_pinned.rs
Original file line number Diff line number Diff line change
@@ -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);
}
11 changes: 0 additions & 11 deletions examples/next_unpinned.rs

This file was deleted.

4 changes: 2 additions & 2 deletions examples/size_hint.rs
Original file line number Diff line number Diff line change
@@ -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());

37 changes: 19 additions & 18 deletions examples/take.rs
Original file line number Diff line number Diff line change
@@ -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);
}
14 changes: 7 additions & 7 deletions examples/tear.rs
Original file line number Diff line number Diff line change
@@ -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);
}
87 changes: 42 additions & 45 deletions src/event_iter.rs
Original file line number Diff line number Diff line change
@@ -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<Self::Event<'a>>;

/// 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.
///
8 changes: 7 additions & 1 deletion src/from_iter.rs
Original file line number Diff line number Diff line change
@@ -62,7 +62,13 @@ where
}

fn size_hint(&self) -> (usize, Option<usize>) {
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)
}
}
}

8 changes: 7 additions & 1 deletion src/from_iter_mut.rs
Original file line number Diff line number Diff line change
@@ -62,7 +62,13 @@ where
}

fn size_hint(&self) -> (usize, Option<usize>) {
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)
}
}
}

4 changes: 1 addition & 3 deletions src/inspect.rs
Original file line number Diff line number Diff line change
@@ -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);

2 changes: 1 addition & 1 deletion src/next.rs
Original file line number Diff line number Diff line change
@@ -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<Pin<&'a mut Ei>>);
2 changes: 2 additions & 0 deletions src/take.rs
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@ pin_project_lite::pin_project! {

impl<I> Take<I> {
pub(crate) fn new(ei: I, count: usize) -> Self {
let count = count.checked_add(1).expect("overflow in take");

Self { ei, count }
}
}