async_std/io/buf_read/
split.rs

1use std::mem;
2use std::pin::Pin;
3
4use pin_project_lite::pin_project;
5
6use super::read_until_internal;
7use crate::io::{self, BufRead};
8use crate::stream::Stream;
9use crate::task::{Context, Poll};
10
11pin_project! {
12    /// A stream over the contents of an instance of [`BufRead`] split on a particular byte.
13    ///
14    /// This stream is created by the [`split`] method on types that implement [`BufRead`].
15    ///
16    /// This type is an async version of [`std::io::Split`].
17    ///
18    /// [`split`]: trait.BufRead.html#method.lines
19    /// [`BufRead`]: trait.BufRead.html
20    /// [`std::io::Split`]: https://doc.rust-lang.org/std/io/struct.Split.html
21    #[derive(Debug)]
22    pub struct Split<R> {
23        #[pin]
24        pub(crate) reader: R,
25        pub(crate) buf: Vec<u8>,
26        pub(crate) read: usize,
27        pub(crate) delim: u8,
28    }
29}
30
31impl<R: BufRead> Stream for Split<R> {
32    type Item = io::Result<Vec<u8>>;
33
34    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
35        let this = self.project();
36        let n = futures_core::ready!(read_until_internal(
37            this.reader,
38            cx,
39            *this.delim,
40            this.buf,
41            this.read
42        ))?;
43        if n == 0 && this.buf.is_empty() {
44            return Poll::Ready(None);
45        }
46        if this.buf[this.buf.len() - 1] == *this.delim {
47            this.buf.pop();
48        }
49        Poll::Ready(Some(Ok(mem::replace(this.buf, vec![]))))
50    }
51}