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: Projection<'_, R> = self.project();
36 let n: usize = 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(dest:this.buf, src:vec![]))))
50 }
51}
52