tokio_util/io/stream_reader.rs
1use bytes::Buf;
2use futures_core::stream::Stream;
3use futures_sink::Sink;
4use std::io;
5use std::pin::Pin;
6use std::task::{Context, Poll};
7use tokio::io::{AsyncBufRead, AsyncRead, ReadBuf};
8
9/// Convert a [`Stream`] of byte chunks into an [`AsyncRead`].
10///
11/// This type performs the inverse operation of [`ReaderStream`].
12///
13/// This type also implements the [`AsyncBufRead`] trait, so you can use it
14/// to read a `Stream` of byte chunks line-by-line. See the examples below.
15///
16/// # Example
17///
18/// ```
19/// use bytes::Bytes;
20/// use tokio::io::{AsyncReadExt, Result};
21/// use tokio_util::io::StreamReader;
22/// # #[tokio::main(flavor = "current_thread")]
23/// # async fn main() -> std::io::Result<()> {
24///
25/// // Create a stream from an iterator.
26/// let stream = tokio_stream::iter(vec![
27/// Result::Ok(Bytes::from_static(&[0, 1, 2, 3])),
28/// Result::Ok(Bytes::from_static(&[4, 5, 6, 7])),
29/// Result::Ok(Bytes::from_static(&[8, 9, 10, 11])),
30/// ]);
31///
32/// // Convert it to an AsyncRead.
33/// let mut read = StreamReader::new(stream);
34///
35/// // Read five bytes from the stream.
36/// let mut buf = [0; 5];
37/// read.read_exact(&mut buf).await?;
38/// assert_eq!(buf, [0, 1, 2, 3, 4]);
39///
40/// // Read the rest of the current chunk.
41/// assert_eq!(read.read(&mut buf).await?, 3);
42/// assert_eq!(&buf[..3], [5, 6, 7]);
43///
44/// // Read the next chunk.
45/// assert_eq!(read.read(&mut buf).await?, 4);
46/// assert_eq!(&buf[..4], [8, 9, 10, 11]);
47///
48/// // We have now reached the end.
49/// assert_eq!(read.read(&mut buf).await?, 0);
50///
51/// # Ok(())
52/// # }
53/// ```
54///
55/// If the stream produces errors which are not [`std::io::Error`],
56/// the errors can be converted using [`StreamExt`] to map each
57/// element.
58///
59/// ```
60/// use bytes::Bytes;
61/// use tokio::io::AsyncReadExt;
62/// use tokio_util::io::StreamReader;
63/// use tokio_stream::StreamExt;
64/// # #[tokio::main(flavor = "current_thread")]
65/// # async fn main() -> std::io::Result<()> {
66///
67/// // Create a stream from an iterator, including an error.
68/// let stream = tokio_stream::iter(vec![
69/// Result::Ok(Bytes::from_static(&[0, 1, 2, 3])),
70/// Result::Ok(Bytes::from_static(&[4, 5, 6, 7])),
71/// Result::Err("Something bad happened!")
72/// ]);
73///
74/// // Use StreamExt to map the stream and error to a std::io::Error
75/// let stream = stream.map(|result| result.map_err(|err| {
76/// std::io::Error::new(std::io::ErrorKind::Other, err)
77/// }));
78///
79/// // Convert it to an AsyncRead.
80/// let mut read = StreamReader::new(stream);
81///
82/// // Read five bytes from the stream.
83/// let mut buf = [0; 5];
84/// read.read_exact(&mut buf).await?;
85/// assert_eq!(buf, [0, 1, 2, 3, 4]);
86///
87/// // Read the rest of the current chunk.
88/// assert_eq!(read.read(&mut buf).await?, 3);
89/// assert_eq!(&buf[..3], [5, 6, 7]);
90///
91/// // Reading the next chunk will produce an error
92/// let error = read.read(&mut buf).await.unwrap_err();
93/// assert_eq!(error.kind(), std::io::ErrorKind::Other);
94/// assert_eq!(error.into_inner().unwrap().to_string(), "Something bad happened!");
95///
96/// // We have now reached the end.
97/// assert_eq!(read.read(&mut buf).await?, 0);
98///
99/// # Ok(())
100/// # }
101/// ```
102///
103/// Using the [`AsyncBufRead`] impl, you can read a `Stream` of byte chunks
104/// line-by-line. Note that you will usually also need to convert the error
105/// type when doing this. See the second example for an explanation of how
106/// to do this.
107///
108/// ```
109/// use tokio::io::{Result, AsyncBufReadExt};
110/// use tokio_util::io::StreamReader;
111/// # #[tokio::main(flavor = "current_thread")]
112/// # async fn main() -> std::io::Result<()> {
113///
114/// // Create a stream of byte chunks.
115/// let stream = tokio_stream::iter(vec![
116/// Result::Ok(b"The first line.\n".as_slice()),
117/// Result::Ok(b"The second line.".as_slice()),
118/// Result::Ok(b"\nThe third".as_slice()),
119/// Result::Ok(b" line.\nThe fourth line.\nThe fifth line.\n".as_slice()),
120/// ]);
121///
122/// // Convert it to an AsyncRead.
123/// let mut read = StreamReader::new(stream);
124///
125/// // Loop through the lines from the `StreamReader`.
126/// let mut line = String::new();
127/// let mut lines = Vec::new();
128/// loop {
129/// line.clear();
130/// let len = read.read_line(&mut line).await?;
131/// if len == 0 { break; }
132/// lines.push(line.clone());
133/// }
134///
135/// // Verify that we got the lines we expected.
136/// assert_eq!(
137/// lines,
138/// vec![
139/// "The first line.\n",
140/// "The second line.\n",
141/// "The third line.\n",
142/// "The fourth line.\n",
143/// "The fifth line.\n",
144/// ]
145/// );
146/// # Ok(())
147/// # }
148/// ```
149///
150/// [`AsyncRead`]: tokio::io::AsyncRead
151/// [`AsyncBufRead`]: tokio::io::AsyncBufRead
152/// [`Stream`]: futures_core::Stream
153/// [`ReaderStream`]: crate::io::ReaderStream
154/// [`StreamExt`]: https://docs.rs/tokio-stream/latest/tokio_stream/trait.StreamExt.html
155#[derive(Debug)]
156pub struct StreamReader<S, B> {
157 // This field is pinned.
158 inner: S,
159 // This field is not pinned.
160 chunk: Option<B>,
161 eof: bool,
162}
163
164impl<S, B, E> StreamReader<S, B>
165where
166 S: Stream<Item = Result<B, E>>,
167 B: Buf,
168 E: Into<std::io::Error>,
169{
170 /// Convert a stream of byte chunks into an [`AsyncRead`].
171 ///
172 /// The item should be a [`Result`] with the ok variant being something that
173 /// implements the [`Buf`] trait (e.g. `Cursor<Vec<u8>>` or `Bytes`). The error
174 /// should be convertible into an [io error].
175 ///
176 /// [`Result`]: std::result::Result
177 /// [`Buf`]: bytes::Buf
178 /// [io error]: std::io::Error
179 pub fn new(stream: S) -> Self {
180 Self {
181 inner: stream,
182 chunk: None,
183 eof: false,
184 }
185 }
186
187 /// Do we have a chunk and is it non-empty?
188 fn has_chunk(&self) -> bool {
189 if let Some(ref chunk) = self.chunk {
190 chunk.remaining() > 0
191 } else {
192 false
193 }
194 }
195
196 /// Consumes this `StreamReader`, returning a Tuple consisting
197 /// of the underlying stream and an Option of the internal buffer,
198 /// which is Some in case the buffer contains elements.
199 pub fn into_inner_with_chunk(self) -> (S, Option<B>) {
200 if self.has_chunk() {
201 (self.inner, self.chunk)
202 } else {
203 (self.inner, None)
204 }
205 }
206}
207
208impl<S, B> StreamReader<S, B> {
209 /// Gets a reference to the underlying stream.
210 ///
211 /// It is inadvisable to directly read from the underlying stream.
212 pub fn get_ref(&self) -> &S {
213 &self.inner
214 }
215
216 /// Gets a mutable reference to the underlying stream.
217 ///
218 /// It is inadvisable to directly read from the underlying stream.
219 pub fn get_mut(&mut self) -> &mut S {
220 &mut self.inner
221 }
222
223 /// Gets a pinned mutable reference to the underlying stream.
224 ///
225 /// It is inadvisable to directly read from the underlying stream.
226 pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut S> {
227 self.project().inner
228 }
229
230 /// Consumes this `BufWriter`, returning the underlying stream.
231 ///
232 /// Note that any leftover data in the internal buffer is lost.
233 /// If you additionally want access to the internal buffer use
234 /// [`into_inner_with_chunk`].
235 ///
236 /// [`into_inner_with_chunk`]: crate::io::StreamReader::into_inner_with_chunk
237 pub fn into_inner(self) -> S {
238 self.inner
239 }
240}
241
242impl<S, B, E> AsyncRead for StreamReader<S, B>
243where
244 S: Stream<Item = Result<B, E>>,
245 B: Buf,
246 E: Into<std::io::Error>,
247{
248 fn poll_read(
249 mut self: Pin<&mut Self>,
250 cx: &mut Context<'_>,
251 buf: &mut ReadBuf<'_>,
252 ) -> Poll<io::Result<()>> {
253 if buf.remaining() == 0 {
254 return Poll::Ready(Ok(()));
255 }
256
257 let inner_buf = match self.as_mut().poll_fill_buf(cx) {
258 Poll::Ready(Ok(buf)) => buf,
259 Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
260 Poll::Pending => return Poll::Pending,
261 };
262 let len = std::cmp::min(inner_buf.len(), buf.remaining());
263 buf.put_slice(&inner_buf[..len]);
264
265 self.consume(len);
266 Poll::Ready(Ok(()))
267 }
268}
269
270impl<S, B, E> AsyncBufRead for StreamReader<S, B>
271where
272 S: Stream<Item = Result<B, E>>,
273 B: Buf,
274 E: Into<std::io::Error>,
275{
276 fn poll_fill_buf(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
277 loop {
278 if self.as_mut().has_chunk() {
279 // This unwrap is very sad, but it can't be avoided.
280 let buf = self.project().chunk.as_ref().unwrap().chunk();
281 return Poll::Ready(Ok(buf));
282 } else if *self.as_mut().project().eof {
283 return Poll::Ready(Ok(&[]));
284 } else {
285 match self.as_mut().project().inner.poll_next(cx) {
286 Poll::Ready(Some(Ok(chunk))) => {
287 // Go around the loop in case the chunk is empty.
288 *self.as_mut().project().chunk = Some(chunk);
289 }
290 Poll::Ready(Some(Err(err))) => return Poll::Ready(Err(err.into())),
291 Poll::Ready(None) => {
292 *self.as_mut().project().eof = true;
293 return Poll::Ready(Ok(&[]));
294 }
295 Poll::Pending => return Poll::Pending,
296 }
297 }
298 }
299 }
300 fn consume(self: Pin<&mut Self>, amt: usize) {
301 if amt > 0 {
302 self.project()
303 .chunk
304 .as_mut()
305 .expect("No chunk present")
306 .advance(amt);
307 }
308 }
309}
310
311// The code below is a manual expansion of the code that pin-project-lite would
312// generate. This is done because pin-project-lite fails by hitting the recursion
313// limit on this struct. (Every line of documentation is handled recursively by
314// the macro.)
315
316impl<S: Unpin, B> Unpin for StreamReader<S, B> {}
317
318struct StreamReaderProject<'a, S, B> {
319 inner: Pin<&'a mut S>,
320 chunk: &'a mut Option<B>,
321 eof: &'a mut bool,
322}
323
324impl<S, B> StreamReader<S, B> {
325 #[inline]
326 fn project(self: Pin<&mut Self>) -> StreamReaderProject<'_, S, B> {
327 // SAFETY: We define that only `inner` should be pinned when `Self` is
328 // and have an appropriate `impl Unpin` for this.
329 let me = unsafe { Pin::into_inner_unchecked(self) };
330 StreamReaderProject {
331 inner: unsafe { Pin::new_unchecked(&mut me.inner) },
332 chunk: &mut me.chunk,
333 eof: &mut me.eof,
334 }
335 }
336}
337
338impl<S: Sink<T, Error = E>, B, E, T> Sink<T> for StreamReader<S, B> {
339 type Error = E;
340 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
341 self.project().inner.poll_ready(cx)
342 }
343
344 fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> {
345 self.project().inner.start_send(item)
346 }
347
348 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
349 self.project().inner.poll_flush(cx)
350 }
351
352 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
353 self.project().inner.poll_close(cx)
354 }
355}