@ -1,9 +1,7 @@
mod fill_buf ;
mod lines ;
mod lines ;
mod read_line ;
mod read_line ;
mod read_until ;
mod read_until ;
use fill_buf ::FillBufFuture ;
pub use lines ::Lines ;
pub use lines ::Lines ;
use read_line ::ReadLineFuture ;
use read_line ::ReadLineFuture ;
use read_until ::ReadUntilFuture ;
use read_until ::ReadUntilFuture ;
@ -12,115 +10,259 @@ use std::mem;
use std ::pin ::Pin ;
use std ::pin ::Pin ;
use cfg_if ::cfg_if ;
use cfg_if ::cfg_if ;
use futures_io ::AsyncBufRead ;
use crate ::io ;
use crate ::io ;
use crate ::task ::{ Context , Poll } ;
use crate ::task ::{ Context , Poll } ;
cfg_if ! {
cfg_if ! {
if #[ cfg(feature = " docs " ) ] {
if #[ cfg(feature = " docs " ) ] {
use std ::ops ::{ Deref , DerefMut } ;
#[ doc(hidden) ]
#[ doc(hidden) ]
pub struct ImplFuture < ' a , T > ( std ::marker ::PhantomData < & ' a T > ) ;
pub struct ImplFuture < ' a , T > ( std ::marker ::PhantomData < & ' a T > ) ;
macro_rules! ret {
/// Allows reading from a buffered byte stream.
( $a :lifetime , $f :tt , $o :ty ) = > ( ImplFuture < $a , $o > ) ;
///
/// 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 {
/// 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 < io ::Result < & [ u8 ] > > ;
/// 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 ) ;
/// 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 < u8 > ,
) -> ImplFuture < ' a , io ::Result < usize > >
where
Self : Unpin ,
{
unreachable! ( )
}
/// 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 ,
) -> ImplFuture < ' a , io ::Result < usize > >
where
Self : Unpin ,
{
unreachable! ( )
}
/// 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 < Self >
where
Self : Unpin + Sized ,
{
unreachable! ( )
}
}
}
} else {
macro_rules! ret {
impl < T : BufRead + Unpin + ? Sized > BufRead for Box < T > {
( $a :lifetime , $f :tt , $o :ty ) = > ( $f < $a , Self > ) ;
fn poll_fill_buf (
self : Pin < & mut Self > ,
cx : & mut Context < ' _ > ,
) -> Poll < io ::Result < & [ u8 ] > > {
unreachable! ( )
}
fn consume ( self : Pin < & mut Self > , amt : usize ) {
unreachable! ( )
}
}
}
}
}
/// Allows reading from a buffered byte stream.
impl < T : BufRead + Unpin + ? Sized > BufRead for & mut T {
///
fn poll_fill_buf (
/// This trait is an async version of [`std::io::BufRead`].
self : Pin < & mut Self > ,
///
cx : & mut Context < ' _ > ,
/// While it is currently not possible to implement this trait directly, it gets implemented
) -> Poll < io ::Result < & [ u8 ] > > {
/// automatically for all types that implement [`futures::io::AsyncBufRead`].
unreachable! ( )
///
}
/// [`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
pub trait BufRead {
/// 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 ( & mut self , amt : usize )
where
Self : Unpin ;
/// Returns the contents of the internal buffer, filling it with more data from the inner
fn consume ( self : Pin < & mut Self > , amt : usize ) {
/// reader if it is empty.
unreachable! ( )
///
}
/// 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
impl < P > BufRead for Pin < P >
/// called with the number of bytes that are consumed from this buffer to ensure that the bytes
where
/// are never returned twice.
P : DerefMut + Unpin ,
///
< P as Deref > ::Target : BufRead ,
/// [`consume`]: #tymethod.consume
{
///
fn poll_fill_buf (
/// An empty buffer returned indicates that the stream has reached EOF.
self : Pin < & mut Self > ,
// TODO: write a proper doctest with `consume`
cx : & mut Context < ' _ > ,
fn fill_buf < ' a > ( & ' a mut self ) -> ret ! ( ' a , FillBufFuture , io ::Result < & ' a [ u8 ] > )
) -> Poll < io ::Result < & [ u8 ] > > {
where
unreachable! ( )
Self : Unpin ,
}
{
FillBufFuture ::new ( self )
fn consume ( self : Pin < & mut Self > , amt : usize ) {
unreachable! ( )
}
}
impl BufRead for & [ u8 ] {
fn poll_fill_buf (
self : Pin < & mut Self > ,
cx : & mut Context < ' _ > ,
) -> Poll < io ::Result < & [ u8 ] > > {
unreachable! ( )
}
fn consume ( self : Pin < & mut Self > , amt : usize ) {
unreachable! ( )
}
}
} else {
pub use futures_io ::AsyncBufRead as BufRead ;
}
}
}
/// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
#[ doc(hidden) ]
///
pub trait BufReadExt : futures_io ::AsyncBufRead {
/// This function will read bytes from the underlying stream until the delimiter or EOF is
fn read_until < ' a > ( & ' a mut self , byte : u8 , buf : & ' a mut Vec < u8 > ) -> ReadUntilFuture < ' a , Self >
/// 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 < u8 > ,
) -> ret ! ( ' a , ReadUntilFuture , io ::Result < usize > )
where
where
Self : Unpin ,
Self : Unpin ,
{
{
@ -132,44 +274,7 @@ pub trait BufRead {
}
}
}
}
/// Reads all bytes and appends them into `buf` until a newline (the 0xA byte) is reached.
fn read_line < ' a > ( & ' a mut self , buf : & ' a mut String ) -> ReadLineFuture < ' a , Self >
///
/// 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 ,
) -> ret ! ( ' a , ReadLineFuture , io ::Result < usize > )
where
where
Self : Unpin ,
Self : Unpin ,
{
{
@ -181,35 +286,6 @@ pub trait BufRead {
}
}
}
}
/// 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 < Self >
fn lines ( self ) -> Lines < Self >
where
where
Self : Unpin + Sized ,
Self : Unpin + Sized ,
@ -223,13 +299,9 @@ pub trait BufRead {
}
}
}
}
impl < T : AsyncBufRead + Unpin + ? Sized > BufRead for T {
impl < T : futures_io ::AsyncBufRead + ? Sized > BufReadExt for T { }
fn consume ( & mut self , amt : usize ) {
AsyncBufRead ::consume ( Pin ::new ( self ) , amt )
}
}
pub fn read_until_internal < R : Async BufRead + ? Sized > (
pub fn read_until_internal < R : BufReadExt + ? Sized > (
mut reader : Pin < & mut R > ,
mut reader : Pin < & mut R > ,
cx : & mut Context < ' _ > ,
cx : & mut Context < ' _ > ,
byte : u8 ,
byte : u8 ,