lending_stream/
next.rs

1use crate::LendingStream;
2use std::{
3    future::Future,
4    pin::Pin,
5    task::{Context, Poll},
6};
7
8/// Future for the [`StreamExt::next()`] method.
9#[derive(Debug)]
10#[must_use = "futures do nothing unless you `.await` or poll them"]
11// #[pin_project]
12pub struct Next<'a, S: ?Sized + Unpin> {
13    stream: &'a mut S,
14    done: bool,
15}
16
17impl<'a, S: ?Sized + Unpin> Next<'a, S> {
18    /// Create a new instance of `Next`.
19    pub(crate) fn new(stream: &'a mut S) -> Self {
20        Self {
21            stream,
22            done: false,
23        }
24    }
25}
26
27impl<S: Unpin + ?Sized> Unpin for Next<'_, S> {}
28
29impl<'a, S: LendingStream + Unpin + ?Sized> Future for Next<'a, S> {
30    type Output = Option<S::Item<'a>>;
31
32    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
33        let Self {
34            stream,
35            done: is_done,
36        } = self.get_mut();
37
38        // This prevents access to the underlying iterator after the future has
39        // completed, ensuring mutable access does not overlap between  futures.
40        assert!(!*is_done, "Cannot poll future after it has been `.await`ed");
41
42        // SAFETY: this seems to be the only way to read from the pointer
43        // without getting lifetime errors. We know this should be possible
44        // because we have a sugared version of this in
45        // `async_iterator::LendingIterator`. And from the documentation of
46        // `ptr::read` it doesn't seem like we're violating any invariants, nor are
47        // we returning any wrong lifetimes.
48        match unsafe { std::ptr::read(stream) }.poll_next(cx) {
49            Poll::Ready(ready) => {
50                *is_done = true;
51                Poll::Ready(ready)
52            }
53            Poll::Pending => todo!(),
54        }
55    }
56}