mod lines; mod read_line; mod read_until; mod split; pub use lines::Lines; pub use split::Split; use read_line::ReadLineFuture; use read_until::ReadUntilFuture; use std::mem; use std::pin::Pin; use crate::io; use crate::task::{Context, Poll}; extension_trait! { use std::ops::{Deref, DerefMut}; #[doc = r#" Allows reading from a buffered byte stream. This trait is a re-export of [`futures::io::AsyncBufRead`] and is an async version of [`std::io::BufRead`]. The [provided methods] do not really exist in the trait itself, but they become available when the prelude is imported: ``` # #[allow(unused_imports)] use async_std::prelude::*; ``` [`std::io::BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html [`futures::io::AsyncBufRead`]: https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncBufRead.html [provided methods]: #provided-methods "#] pub trait BufRead { #[doc = r#" Returns the contents of the internal buffer, filling it with more data from the inner reader if it is empty. This function is a lower-level call. It needs to be paired with the [`consume`] method to function properly. When calling this method, none of the contents will be "read" in the sense that later calling `read` may return the same contents. As such, [`consume`] must be called with the number of bytes that are consumed from this buffer to ensure that the bytes are never returned twice. [`consume`]: #tymethod.consume An empty buffer returned indicates that the stream has reached EOF. "#] // TODO: write a proper doctest with `consume` fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; #[doc = r#" Tells this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `read`. "#] fn consume(self: Pin<&mut Self>, amt: usize); } pub trait BufReadExt: futures_io::AsyncBufRead { #[doc = r#" Reads all bytes into `buf` until the delimiter `byte` or EOF is reached. This function will read bytes from the underlying stream until the delimiter or EOF is found. Once found, all bytes up to, and including, the delimiter (if found) will be appended to `buf`. If successful, this function will return the total number of bytes read. # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::io::BufReader; use async_std::prelude::*; let mut file = BufReader::new(File::open("a.txt").await?); let mut buf = Vec::with_capacity(1024); let n = file.read_until(b'\n', &mut buf).await?; # # Ok(()) }) } ``` Multiple successful calls to `read_until` append all bytes up to and including to `buf`: ``` # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::io::BufReader; use async_std::prelude::*; let from: &[u8] = b"append\nexample\n"; let mut reader = BufReader::new(from); let mut buf = vec![]; let mut size = reader.read_until(b'\n', &mut buf).await?; assert_eq!(size, 7); assert_eq!(buf, b"append\n"); size += reader.read_until(b'\n', &mut buf).await?; assert_eq!(size, from.len()); assert_eq!(buf, from); # # Ok(()) }) } ``` "#] fn read_until<'a>( &'a mut self, byte: u8, buf: &'a mut Vec, ) -> impl Future + 'a [ReadUntilFuture<'a, Self>] where Self: Unpin, { ReadUntilFuture { reader: self, byte, buf, read: 0, } } #[doc = r#" Reads all bytes and appends them into `buf` until a newline (the 0xA byte) is reached. This function will read bytes from the underlying stream until the newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes up to, and including, the delimiter (if found) will be appended to `buf`. If successful, this function will return the total number of bytes read. If this function returns `Ok(0)`, the stream has reached EOF. # Errors This function has the same error semantics as [`read_until`] and will also return an error if the read bytes are not valid UTF-8. If an I/O error is encountered then `buf` may contain some bytes already read in the event that all data read so far was valid UTF-8. [`read_until`]: #method.read_until # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::io::BufReader; use async_std::prelude::*; let mut file = BufReader::new(File::open("a.txt").await?); let mut buf = String::new(); file.read_line(&mut buf).await?; # # Ok(()) }) } ``` "#] fn read_line<'a>( &'a mut self, buf: &'a mut String, ) -> impl Future> + 'a [ReadLineFuture<'a, Self>] where Self: Unpin, { ReadLineFuture { reader: self, bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) }, buf, read: 0, } } #[doc = r#" Returns a stream over the lines of this byte stream. The stream returned from this function will yield instances of [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. [`io::Result`]: type.Result.html [`String`]: https://doc.rust-lang.org/std/string/struct.String.html # Examples ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::fs::File; use async_std::io::BufReader; use async_std::prelude::*; let file = File::open("a.txt").await?; let mut lines = BufReader::new(file).lines(); let mut count = 0; while let Some(line) = lines.next().await { line?; count += 1; } # # Ok(()) }) } ``` "#] fn lines(self) -> Lines where Self: Unpin + Sized, { Lines { reader: self, buf: String::new(), bytes: Vec::new(), read: 0, } } #[doc = r#" Returns a stream over the contents of this reader split on the byte `byte`. The stream returned from this function will return instances of [`io::Result`]`<`[`Vec`]`>`. Each vector returned will *not* have the delimiter byte at the end. This function will yield errors whenever [`read_until`] would have also yielded an error. [`io::Result`]: type.Result.html [`Vec`]: ../vec/struct.Vec.html [`read_until`]: #method.read_until # Examples [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In this example, we use [`Cursor`] to iterate over all hyphen delimited segments in a byte slice [`Cursor`]: struct.Cursor.html ``` # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::io; let cursor = io::Cursor::new(b"lorem-ipsum-dolor"); let mut split_iter = cursor.split(b'-').map(|l| l.unwrap()); assert_eq!(split_iter.next().await, Some(b"lorem".to_vec())); assert_eq!(split_iter.next().await, Some(b"ipsum".to_vec())); assert_eq!(split_iter.next().await, Some(b"dolor".to_vec())); assert_eq!(split_iter.next().await, None); # # Ok(()) }) } ``` "#] fn split(self, byte: u8) -> Split where Self: Sized, { Split { reader: self, buf: Vec::new(), delim: byte, read: 0, } } } impl BufRead for Box { fn poll_fill_buf( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { unreachable!("this impl only appears in the rendered docs") } fn consume(self: Pin<&mut Self>, amt: usize) { unreachable!("this impl only appears in the rendered docs") } } impl BufRead for &mut T { fn poll_fill_buf( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { unreachable!("this impl only appears in the rendered docs") } fn consume(self: Pin<&mut Self>, amt: usize) { unreachable!("this impl only appears in the rendered docs") } } impl

BufRead for Pin

where P: DerefMut + Unpin,

::Target: BufRead, { fn poll_fill_buf( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { unreachable!("this impl only appears in the rendered docs") } fn consume(self: Pin<&mut Self>, amt: usize) { unreachable!("this impl only appears in the rendered docs") } } impl BufRead for &[u8] { fn poll_fill_buf( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { unreachable!() } fn consume(self: Pin<&mut Self>, amt: usize) { unreachable!("this impl only appears in the rendered docs") } } } pub fn read_until_internal( mut reader: Pin<&mut R>, cx: &mut Context<'_>, byte: u8, buf: &mut Vec, read: &mut usize, ) -> Poll> { loop { let (done, used) = { let available = futures_core::ready!(reader.as_mut().poll_fill_buf(cx))?; if let Some(i) = memchr::memchr(byte, available) { buf.extend_from_slice(&available[..=i]); (true, i + 1) } else { buf.extend_from_slice(available); (false, available.len()) } }; reader.as_mut().consume(used); *read += used; if done || used == 0 { return Poll::Ready(Ok(mem::replace(read, 0))); } } }