use std::mem; use std::pin::Pin; use pin_project_lite::pin_project; use super::read_until_internal; use crate::io::{self, BufRead}; use crate::stream::Stream; use crate::task::{Context, Poll}; pin_project! { /// A stream over the contents of an instance of [`BufRead`] split on a particular byte. /// /// This stream is created by the [`split`] method on types that implement [`BufRead`]. /// /// This type is an async version of [`std::io::Split`]. /// /// [`split`]: trait.BufRead.html#method.lines /// [`BufRead`]: trait.BufRead.html /// [`std::io::Split`]: https://doc.rust-lang.org/std/io/struct.Split.html #[derive(Debug)] pub struct Split { #[pin] pub(crate) reader: R, pub(crate) buf: Vec, pub(crate) read: usize, pub(crate) delim: u8, } } impl Stream for Split { type Item = io::Result>; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let n = futures_core::ready!(read_until_internal( this.reader, cx, *this.delim, this.buf, this.read ))?; if n == 0 && this.buf.is_empty() { return Poll::Ready(None); } if this.buf[this.buf.len() - 1] == *this.delim { this.buf.pop(); } Poll::Ready(Some(Ok(mem::replace(this.buf, vec![])))) } }