async_buf_read/
lib.rs

1use std::ops::DerefMut;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
5pub use self::buf_read_ext::AsyncBufReadExt;
6pub use self::buf_reader::AsyncBufReader;
7pub use self::passthrough::AsyncBufPassthrough;
8
9mod buf_read_ext;
10mod buf_reader;
11mod io;
12mod passthrough;
13mod peek;
14
15/// Reads bytes asynchronously and buffers them.
16///
17/// Utilities for working with `AsyncBufRead` values are provided by
18/// [`AsyncBufReadExt`].
19///
20/// [`AsyncBufReadExt`]: crate::AsyncBufReadExt
21pub trait AsyncBufRead: io::AsyncRead {
22    /// Returns true if the inner reader has reached EOF.
23    fn eof(self: Pin<&Self>) -> bool;
24
25    /// Returns a slice of the internal buffer.
26    fn buf(self: Pin<&Self>) -> &[u8];
27
28    /// Attempts to return the contents of the internal buffer, filling it with more
29    /// data from the inner reader if it less than the requested amount.
30    ///
31    /// On success, returns `Poll::Ready(Ok(buf))`.
32    ///
33    /// If no data is available for reading, the method returns
34    /// `Poll::Pending` and arranges for the current task (via
35    /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes
36    /// readable or is closed.
37    ///
38    /// This function doesn't consume the data, it only returns a slice up
39    /// to the requested amount. This means that subsequent calls to [`poll_read`]
40    /// will return the same contents. As such, [`consume`] can be called
41    /// with the number of bytes that are consumed from this buffer to
42    /// ensure that the bytes are not returned by [`poll_read`].
43    ///
44    /// To check if the inner reader has reached EOF, use [`eof`].
45    ///
46    /// [`poll_read`]: AsyncRead::poll_read
47    /// [`consume`]: AsyncBufRead::consume
48    /// [`eof`]: AsyncBufRead::eof
49    fn poll_fill_buf<'a>(
50        self: Pin<&'a mut Self>,
51        cx: &mut Context<'_>,
52        amt: usize,
53    ) -> Poll<io::Result<&'a [u8]>>;
54
55    /// Tells this buffer that `amt` bytes have been consumed from the buffer,
56    /// so they should no longer be returned in calls to [`poll_read`].
57    ///
58    /// This function is a lower-level call. It needs to be paired with the
59    /// [`poll_fill_buf`] method to function properly. This function does
60    /// not perform any I/O, it simply informs this object that some amount of
61    /// its buffer, returned from [`poll_fill_buf`], has been consumed and should
62    /// no longer be returned. As such, this function may do odd things if
63    /// [`poll_fill_buf`] isn't called before calling it.
64    ///
65    /// The `amt` must be `<=` the number of bytes in the buffer returned by
66    /// [`poll_fill_buf`].
67    ///
68    /// [`poll_read`]: AsyncRead::poll_read
69    /// [`poll_fill_buf`]: AsyncBufRead::poll_fill_buf
70    fn consume(self: Pin<&mut Self>, amt: usize);
71}
72
73macro_rules! deref_async_buf_read {
74    () => {
75        fn eof(self: Pin<&Self>) -> bool {
76            Pin::new(&**self.get_ref()).eof()
77        }
78
79        fn buf(self: Pin<&Self>) -> &[u8] {
80            Pin::new(&**self.get_ref()).buf()
81        }
82
83        fn poll_fill_buf(
84            self: Pin<&mut Self>,
85            cx: &mut Context<'_>,
86            amt: usize,
87        ) -> Poll<io::Result<&[u8]>> {
88            Pin::new(&mut **self.get_mut()).poll_fill_buf(cx, amt)
89        }
90
91        fn consume(mut self: Pin<&mut Self>, amt: usize) {
92            Pin::new(&mut **self).consume(amt)
93        }
94    };
95}
96
97impl<T: ?Sized + AsyncBufRead + Unpin> AsyncBufRead for Box<T> {
98    deref_async_buf_read!();
99}
100
101impl<T: ?Sized + AsyncBufRead + Unpin> AsyncBufRead for &mut T {
102    deref_async_buf_read!();
103}
104
105impl<P> AsyncBufRead for Pin<P>
106where
107    P: DerefMut + Unpin,
108    P::Target: AsyncBufRead,
109{
110    fn eof(self: Pin<&Self>) -> bool {
111        self.get_ref().as_ref().eof()
112    }
113
114    fn buf(self: Pin<&Self>) -> &[u8] {
115        self.get_ref().as_ref().buf()
116    }
117
118    fn poll_fill_buf(
119        self: Pin<&mut Self>,
120        cx: &mut Context<'_>,
121        amt: usize,
122    ) -> Poll<io::Result<&[u8]>> {
123        self.get_mut().as_mut().poll_fill_buf(cx, amt)
124    }
125
126    fn consume(self: Pin<&mut Self>, amt: usize) {
127        self.get_mut().as_mut().consume(amt);
128    }
129}
130
131impl AsyncBufRead for &[u8] {
132    fn eof(self: Pin<&Self>) -> bool {
133        false
134    }
135
136    fn buf(self: Pin<&Self>) -> &[u8] {
137        self.get_ref()
138    }
139
140    fn poll_fill_buf(
141        self: Pin<&mut Self>,
142        _cx: &mut Context<'_>,
143        amt: usize,
144    ) -> Poll<io::Result<&[u8]>> {
145        let amt = std::cmp::min(self.len(), amt);
146        Poll::Ready(Ok(&self[..amt]))
147    }
148
149    fn consume(mut self: Pin<&mut Self>, amt: usize) {
150        *self = &self[amt..];
151    }
152}