futures_util/io/
fill_buf.rs

1use futures_core::future::Future;
2use futures_core::task::{Context, Poll};
3use futures_io::AsyncBufRead;
4use std::io;
5use std::pin::Pin;
6
7/// Future for the [`fill_buf`](super::AsyncBufReadExt::fill_buf) method.
8#[derive(Debug)]
9#[must_use = "futures do nothing unless you `.await` or poll them"]
10pub struct FillBuf<'a, R: ?Sized> {
11    reader: Option<&'a mut R>,
12}
13
14impl<R: ?Sized> Unpin for FillBuf<'_, R> {}
15
16impl<'a, R: AsyncBufRead + ?Sized + Unpin> FillBuf<'a, R> {
17    pub(super) fn new(reader: &'a mut R) -> Self {
18        Self { reader: Some(reader) }
19    }
20}
21
22impl<'a, R> Future for FillBuf<'a, R>
23where
24    R: AsyncBufRead + ?Sized + Unpin,
25{
26    type Output = io::Result<&'a [u8]>;
27
28    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
29        let this = &mut *self;
30        let reader = this.reader.take().expect("Polled FillBuf after completion");
31
32        match Pin::new(&mut *reader).poll_fill_buf(cx) {
33            // With polonius it is possible to remove this inner match and just have the correct
34            // lifetime of the reference inferred based on which branch is taken
35            Poll::Ready(Ok(_)) => match Pin::new(reader).poll_fill_buf(cx) {
36                Poll::Ready(Ok(slice)) => Poll::Ready(Ok(slice)),
37                Poll::Ready(Err(err)) => {
38                    unreachable!("reader indicated readiness but then returned an error: {:?}", err)
39                }
40                Poll::Pending => {
41                    unreachable!("reader indicated readiness but then returned pending")
42                }
43            },
44            Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
45            Poll::Pending => {
46                this.reader = Some(reader);
47                Poll::Pending
48            }
49        }
50    }
51}