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}