2
0
Fork 1
mirror of https://github.com/async-rs/async-std.git synced 2025-02-28 15:19:41 +00:00

Simplify extension traits using a macro

This commit is contained in:
Stjepan Glavina 2019-09-26 07:46:29 -04:00
parent f922e9c034
commit 79eab9eb9a
7 changed files with 1780 additions and 1940 deletions

View file

@ -13,294 +13,266 @@ use cfg_if::cfg_if;
use crate::io; use crate::io;
use crate::task::{Context, Poll}; use crate::task::{Context, Poll};
use crate::utils::extension_trait;
cfg_if! { cfg_if! {
if #[cfg(feature = "docs")] { if #[cfg(feature = "docs")] {
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
}
}
#[doc(hidden)] extension_trait! {
pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); /// 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 [BufReadExt: futures_io::AsyncBufRead] {
/// 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]>>;
/// Allows reading from a buffered byte stream. /// 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 trait is a re-export of [`futures::io::AsyncBufRead`] and is an async version of /// This function will read bytes from the underlying stream until the delimiter or EOF
/// [`std::io::BufRead`]. /// is found. Once found, all bytes up to, and including, the delimiter (if found) will
/// be appended to `buf`.
/// ///
/// The [provided methods] do not really exist in the trait itself, but they become /// If successful, this function will return the total number of bytes read.
/// available when the prelude is imported:
/// ///
/// ``` /// # Examples
/// # #[allow(unused_imports)] ///
/// ```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::*; /// 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(()) }) }
/// ``` /// ```
/// ///
/// [`std::io::BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html /// Multiple successful calls to `read_until` append all bytes up to and including to
/// [`futures::io::AsyncBufRead`]: /// `buf`:
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncBufRead.html /// ```
/// [provided methods]: #provided-methods /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
pub trait BufRead { /// #
/// Returns the contents of the internal buffer, filling it with more data from the /// use async_std::io::BufReader;
/// inner reader if it is empty. /// use async_std::prelude::*;
/// ///
/// This function is a lower-level call. It needs to be paired with the [`consume`] /// let from: &[u8] = b"append\nexample\n";
/// method to function properly. When calling this method, none of the contents will be /// let mut reader = BufReader::new(from);
/// "read" in the sense that later calling `read` may return the same contents. As /// let mut buf = vec![];
/// 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. /// let mut size = reader.read_until(b'\n', &mut buf).await?;
/// /// assert_eq!(size, 7);
/// [`consume`]: #tymethod.consume /// assert_eq!(buf, b"append\n");
/// ///
/// An empty buffer returned indicates that the stream has reached EOF. /// size += reader.read_until(b'\n', &mut buf).await?;
// TODO: write a proper doctest with `consume` /// assert_eq!(size, from.len());
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>>; ///
/// assert_eq!(buf, from);
/// Tells this buffer that `amt` bytes have been consumed from the buffer, so they /// #
/// should no longer be returned in calls to `read`. /// # Ok(()) }) }
fn consume(self: Pin<&mut Self>, amt: usize); /// ```
fn read_until<'a>(
/// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached. &'a mut self,
/// byte: u8,
/// This function will read bytes from the underlying stream until the delimiter or EOF buf: &'a mut Vec<u8>,
/// is found. Once found, all bytes up to, and including, the delimiter (if found) will ) -> impl Future<Output = usize> + 'a [ReadUntilFuture<'a, Self>]
/// 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!()
}
}
impl<T: BufRead + Unpin + ?Sized> BufRead for Box<T> {
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!()
}
}
impl<T: BufRead + Unpin + ?Sized> BufRead for &mut T {
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!()
}
}
impl<P> BufRead for Pin<P>
where where
P: DerefMut + Unpin, Self: Unpin,
<P as Deref>::Target: BufRead,
{ {
fn poll_fill_buf( ReadUntilFuture {
self: Pin<&mut Self>, reader: self,
cx: &mut Context<'_>, byte,
) -> Poll<io::Result<&[u8]>> { buf,
unreachable!() read: 0,
}
fn consume(self: Pin<&mut Self>, amt: usize) {
unreachable!()
} }
} }
impl BufRead for &[u8] { /// Reads all bytes and appends them into `buf` until a newline (the 0xA byte) is
fn poll_fill_buf( /// reached.
self: Pin<&mut Self>, ///
cx: &mut Context<'_>, /// This function will read bytes from the underlying stream until the newline
) -> Poll<io::Result<&[u8]>> { /// delimiter (the 0xA byte) or EOF is found. Once found, all bytes up to, and
unreachable!() /// including, the delimiter (if found) will be appended to `buf`.
} ///
/// If successful, this function will return the total number of bytes read.
fn consume(self: Pin<&mut Self>, amt: usize) { ///
unreachable!() /// 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<Output = io::Result<usize>> + 'a [ReadLineFuture<'a, Self>]
where
Self: Unpin,
{
ReadLineFuture {
reader: self,
bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) },
buf,
read: 0,
} }
} }
} else {
pub use futures_io::AsyncBufRead as BufRead;
}
}
#[doc(hidden)] /// Returns a stream over the lines of this byte stream.
pub trait BufReadExt: futures_io::AsyncBufRead { ///
fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntilFuture<'a, Self> /// The stream returned from this function will yield instances of
where /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline byte
Self: Unpin, /// (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
{ ///
ReadUntilFuture { /// [`io::Result`]: type.Result.html
reader: self, /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
byte, ///
buf, /// # Examples
read: 0, ///
/// ```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,
{
Lines {
reader: self,
buf: String::new(),
bytes: Vec::new(),
read: 0,
}
} }
} }
fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLineFuture<'a, Self> impl<T: BufRead + Unpin + ?Sized> BufRead for Box<T> {
where fn poll_fill_buf(
Self: Unpin, self: Pin<&mut Self>,
{ cx: &mut Context<'_>,
ReadLineFuture { ) -> Poll<io::Result<&[u8]>> {
reader: self, unreachable!()
bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) }, }
buf,
read: 0, fn consume(self: Pin<&mut Self>, amt: usize) {
unreachable!()
} }
} }
fn lines(self) -> Lines<Self> impl<T: BufRead + Unpin + ?Sized> BufRead for &mut T {
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!()
}
}
impl<P> BufRead for Pin<P>
where where
Self: Unpin + Sized, P: DerefMut + Unpin,
<P as Deref>::Target: BufRead,
{ {
Lines { fn poll_fill_buf(
reader: self, self: Pin<&mut Self>,
buf: String::new(), cx: &mut Context<'_>,
bytes: Vec::new(), ) -> Poll<io::Result<&[u8]>> {
read: 0, unreachable!()
}
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!()
} }
} }
} }
impl<T: futures_io::AsyncBufRead + ?Sized> BufReadExt for T {}
pub fn read_until_internal<R: BufReadExt + ?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<'_>,

View file

@ -11,10 +11,10 @@ use read_to_string::ReadToStringFuture;
use read_vectored::ReadVectoredFuture; use read_vectored::ReadVectoredFuture;
use std::mem; use std::mem;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use crate::io::IoSliceMut; use crate::io::IoSliceMut;
use crate::utils::extension_trait;
cfg_if! { cfg_if! {
if #[cfg(feature = "docs")] { if #[cfg(feature = "docs")] {
@ -23,311 +23,265 @@ cfg_if! {
use crate::io; use crate::io;
use crate::task::{Context, Poll}; use crate::task::{Context, Poll};
}
}
#[doc(hidden)] extension_trait! {
pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); /// Allows reading from a byte stream.
///
/// This trait is a re-export of [`futures::io::AsyncRead`] and is an async version of
/// [`std::io::Read`].
///
/// Methods other than [`poll_read`] and [`poll_read_vectored`] 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::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
/// [`futures::io::AsyncRead`]:
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncRead.html
/// [`poll_read`]: #tymethod.poll_read
/// [`poll_read_vectored`]: #method.poll_read_vectored
pub trait Read [ReadExt: futures_io::AsyncRead] {
/// Attempt to read from the `AsyncRead` into `buf`.
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>>;
/// Allows reading from a byte stream. /// Attempt to read from the `AsyncRead` into `bufs` using vectored IO operations.
fn poll_read_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &mut [IoSliceMut<'_>],
) -> Poll<io::Result<usize>> {
unreachable!()
}
/// Reads some bytes from the byte stream.
/// ///
/// This trait is a re-export of [`futures::io::AsyncRead`] and is an async version of /// Returns the number of bytes read from the start of the buffer.
/// [`std::io::Read`].
/// ///
/// Methods other than [`poll_read`] and [`poll_read_vectored`] do not really exist in the /// If the return value is `Ok(n)`, then it must be guaranteed that
/// trait itself, but they become available when the prelude is imported: /// `0 <= n <= buf.len()`. A nonzero `n` value indicates that the buffer has been
/// filled in with `n` bytes of data. If `n` is `0`, then it can indicate one of two
/// scenarios:
/// ///
/// ``` /// 1. This reader has reached its "end of file" and will likely no longer be able to
/// # #[allow(unused_imports)] /// produce bytes. Note that this does not mean that the reader will always no
/// longer be able to produce bytes.
/// 2. The buffer specified was 0 bytes in length.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// ```
/// ///
/// [`std::io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// let mut file = File::open("a.txt").await?;
/// [`futures::io::AsyncRead`]: ///
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncRead.html /// let mut buf = vec![0; 1024];
/// [`poll_read`]: #tymethod.poll_read /// let n = file.read(&mut buf).await?;
/// [`poll_read_vectored`]: #method.poll_read_vectored /// #
pub trait Read { /// # Ok(()) }) }
/// Attempt to read from the `AsyncRead` into `buf`. /// ```
fn poll_read( fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future<Output = io::Result<usize>> + 'a [ReadFuture<'a, Self>]
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>>;
/// Attempt to read from the `AsyncRead` into `bufs` using vectored IO operations.
fn poll_read_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &mut [IoSliceMut<'_>],
) -> Poll<io::Result<usize>> {
unreachable!()
}
/// Reads some bytes from the byte stream.
///
/// Returns the number of bytes read from the start of the buffer.
///
/// If the return value is `Ok(n)`, then it must be guaranteed that
/// `0 <= n <= buf.len()`. A nonzero `n` value indicates that the buffer has been
/// filled in with `n` bytes of data. If `n` is `0`, then it can indicate one of two
/// scenarios:
///
/// 1. This reader has reached its "end of file" and will likely no longer be able to
/// produce bytes. Note that this does not mean that the reader will always no
/// longer be able to produce bytes.
/// 2. The buffer specified was 0 bytes in length.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let mut buf = vec![0; 1024];
/// let n = file.read(&mut buf).await?;
/// #
/// # Ok(()) }) }
/// ```
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> ImplFuture<'a, io::Result<usize>>
where
Self: Unpin
{
unreachable!()
}
/// Like [`read`], except that it reads into a slice of buffers.
///
/// Data is copied to fill each buffer in order, with the final buffer written to
/// possibly being only partially filled. This method must behave as a single call to
/// [`read`] with the buffers concatenated would.
///
/// The default implementation calls [`read`] with either the first nonempty buffer
/// provided, or an empty one if none exists.
///
/// [`read`]: #tymethod.read
fn read_vectored<'a>(
&'a mut self,
bufs: &'a mut [IoSliceMut<'a>],
) -> ImplFuture<'a, io::Result<usize>>
where
Self: Unpin,
{
unreachable!()
}
/// Reads all bytes from the byte stream.
///
/// All bytes read from this stream will be appended to the specified buffer `buf`.
/// This function will continuously call [`read`] to append more data to `buf` until
/// [`read`] returns either `Ok(0)` or an error.
///
/// If successful, this function will return the total number of bytes read.
///
/// [`read`]: #tymethod.read
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let mut buf = Vec::new();
/// file.read_to_end(&mut buf).await?;
/// #
/// # Ok(()) }) }
/// ```
fn read_to_end<'a>(
&'a mut self,
buf: &'a mut Vec<u8>,
) -> ImplFuture<'a, io::Result<usize>>
where
Self: Unpin,
{
unreachable!()
}
/// Reads all bytes from the byte stream and appends them into a string.
///
/// If successful, this function will return the number of bytes read.
///
/// If the data in this stream is not valid UTF-8 then an error will be returned and
/// `buf` will be left unmodified.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let mut buf = String::new();
/// file.read_to_string(&mut buf).await?;
/// #
/// # Ok(()) }) }
/// ```
fn read_to_string<'a>(
&'a mut self,
buf: &'a mut String,
) -> ImplFuture<'a, io::Result<usize>>
where
Self: Unpin,
{
unreachable!()
}
/// Reads the exact number of bytes required to fill `buf`.
///
/// This function reads as many bytes as necessary to completely fill the specified
/// buffer `buf`.
///
/// No guarantees are provided about the contents of `buf` when this function is
/// called, implementations cannot rely on any property of the contents of `buf` being
/// true. It is recommended that implementations only write data to `buf` instead of
/// reading its contents.
///
/// If this function encounters an "end of file" before completely filling the buffer,
/// it returns an error of the kind [`ErrorKind::UnexpectedEof`]. The contents of
/// `buf` are unspecified in this case.
///
/// If any other read error is encountered then this function immediately returns. The
/// contents of `buf` are unspecified in this case.
///
/// If this function returns an error, it is unspecified how many bytes it has read,
/// but it will never read more than would be necessary to completely fill the buffer.
///
/// [`ErrorKind::UnexpectedEof`]: enum.ErrorKind.html#variant.UnexpectedEof
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let mut buf = vec![0; 10];
/// file.read_exact(&mut buf).await?;
/// #
/// # Ok(()) }) }
/// ```
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ImplFuture<'a, io::Result<()>>
where
Self: Unpin,
{
unreachable!()
}
}
impl<T: Read + Unpin + ?Sized> Read for Box<T> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
}
impl<T: Read + Unpin + ?Sized> Read for &mut T {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
}
impl<P> Read for Pin<P>
where where
P: DerefMut + Unpin, Self: Unpin
<P as Deref>::Target: Read,
{ {
fn poll_read( ReadFuture { reader: self, buf }
self: Pin<&mut Self>, }
cx: &mut Context<'_>,
buf: &mut [u8], /// Like [`read`], except that it reads into a slice of buffers.
) -> Poll<io::Result<usize>> { ///
unreachable!() /// Data is copied to fill each buffer in order, with the final buffer written to
/// possibly being only partially filled. This method must behave as a single call to
/// [`read`] with the buffers concatenated would.
///
/// The default implementation calls [`read`] with either the first nonempty buffer
/// provided, or an empty one if none exists.
///
/// [`read`]: #tymethod.read
fn read_vectored<'a>(
&'a mut self,
bufs: &'a mut [IoSliceMut<'a>],
) -> impl Future<Output = io::Result<usize>> + 'a [ReadVectoredFuture<'a, Self>]
where
Self: Unpin,
{
ReadVectoredFuture { reader: self, bufs }
}
/// Reads all bytes from the byte stream.
///
/// All bytes read from this stream will be appended to the specified buffer `buf`.
/// This function will continuously call [`read`] to append more data to `buf` until
/// [`read`] returns either `Ok(0)` or an error.
///
/// If successful, this function will return the total number of bytes read.
///
/// [`read`]: #tymethod.read
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let mut buf = Vec::new();
/// file.read_to_end(&mut buf).await?;
/// #
/// # Ok(()) }) }
/// ```
fn read_to_end<'a>(
&'a mut self,
buf: &'a mut Vec<u8>,
) -> impl Future<Output = io::Result<usize>> + 'a [ReadToEndFuture<'a, Self>]
where
Self: Unpin,
{
let start_len = buf.len();
ReadToEndFuture {
reader: self,
buf,
start_len,
} }
} }
impl Read for &[u8] { /// Reads all bytes from the byte stream and appends them into a string.
fn poll_read( ///
self: Pin<&mut Self>, /// If successful, this function will return the number of bytes read.
cx: &mut Context<'_>, ///
buf: &mut [u8], /// If the data in this stream is not valid UTF-8 then an error will be returned and
) -> Poll<io::Result<usize>> { /// `buf` will be left unmodified.
unreachable!() ///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let mut buf = String::new();
/// file.read_to_string(&mut buf).await?;
/// #
/// # Ok(()) }) }
/// ```
fn read_to_string<'a>(
&'a mut self,
buf: &'a mut String,
) -> impl Future<Output = io::Result<usize>> + 'a [ReadToStringFuture<'a, Self>]
where
Self: Unpin,
{
let start_len = buf.len();
ReadToStringFuture {
reader: self,
bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) },
buf,
start_len,
} }
} }
} else {
pub use futures_io::AsyncRead as Read;
}
}
#[doc(hidden)] /// Reads the exact number of bytes required to fill `buf`.
pub trait ReadExt: futures_io::AsyncRead { ///
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadFuture<'a, Self> /// This function reads as many bytes as necessary to completely fill the specified
where /// buffer `buf`.
Self: Unpin, ///
{ /// No guarantees are provided about the contents of `buf` when this function is
ReadFuture { reader: self, buf } /// called, implementations cannot rely on any property of the contents of `buf` being
} /// true. It is recommended that implementations only write data to `buf` instead of
/// reading its contents.
fn read_vectored<'a>( ///
&'a mut self, /// If this function encounters an "end of file" before completely filling the buffer,
bufs: &'a mut [IoSliceMut<'a>], /// it returns an error of the kind [`ErrorKind::UnexpectedEof`]. The contents of
) -> ReadVectoredFuture<'a, Self> /// `buf` are unspecified in this case.
where ///
Self: Unpin, /// If any other read error is encountered then this function immediately returns. The
{ /// contents of `buf` are unspecified in this case.
ReadVectoredFuture { reader: self, bufs } ///
} /// If this function returns an error, it is unspecified how many bytes it has read,
/// but it will never read more than would be necessary to completely fill the buffer.
fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEndFuture<'a, Self> ///
where /// [`ErrorKind::UnexpectedEof`]: enum.ErrorKind.html#variant.UnexpectedEof
Self: Unpin, ///
{ /// # Examples
let start_len = buf.len(); ///
ReadToEndFuture { /// ```no_run
reader: self, /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
buf, /// #
start_len, /// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let mut buf = vec![0; 10];
/// file.read_exact(&mut buf).await?;
/// #
/// # Ok(()) }) }
/// ```
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future<Output = io::Result<()>> + 'a [ReadExactFuture<'a, Self>]
where
Self: Unpin,
{
ReadExactFuture { reader: self, buf }
} }
} }
fn read_to_string<'a>(&'a mut self, buf: &'a mut String) -> ReadToStringFuture<'a, Self> impl<T: Read + Unpin + ?Sized> Read for Box<T> {
where fn poll_read(
Self: Unpin, self: Pin<&mut Self>,
{ cx: &mut Context<'_>,
let start_len = buf.len(); buf: &mut [u8],
ReadToStringFuture { ) -> Poll<io::Result<usize>> {
reader: self, unreachable!()
bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) },
buf,
start_len,
} }
} }
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExactFuture<'a, Self> impl<T: Read + Unpin + ?Sized> Read for &mut T {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
}
impl<P> Read for Pin<P>
where where
Self: Unpin, P: DerefMut + Unpin,
<P as Deref>::Target: Read,
{ {
ReadExactFuture { reader: self, buf } fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
}
impl Read for &[u8] {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
} }
} }
impl<T: futures_io::AsyncRead + ?Sized> ReadExt for T {}

View file

@ -5,119 +5,108 @@ use cfg_if::cfg_if;
use crate::future::Future; use crate::future::Future;
use crate::io::{self, SeekFrom}; use crate::io::{self, SeekFrom};
use crate::task::{Context, Poll}; use crate::task::{Context, Poll};
use crate::utils::extension_trait;
cfg_if! { cfg_if! {
if #[cfg(feature = "docs")] { if #[cfg(feature = "docs")] {
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
}
}
#[doc(hidden)] extension_trait! {
pub struct ImplFuture<T>(std::marker::PhantomData<T>); /// Allows seeking through a byte stream.
///
/// This trait is a re-export of [`futures::io::AsyncSeek`] and is an async version of
/// [`std::io::Seek`].
///
/// 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::Seek`]: https://doc.rust-lang.org/std/io/trait.Seek.html
/// [`futures::io::AsyncSeek`]:
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncSeek.html
/// [provided methods]: #provided-methods
pub trait Seek [SeekExt: futures_io::AsyncSeek] {
/// Attempt to seek to an offset, in bytes, in a stream.
fn poll_seek(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>>;
/// Allows seeking through a byte stream. /// Seeks to a new position in a byte stream.
/// ///
/// This trait is a re-export of [`futures::io::AsyncSeek`] and is an async version of /// Returns the new position in the byte stream.
/// [`std::io::Seek`].
/// ///
/// The [provided methods] do not really exist in the trait itself, but they become /// A seek beyond the end of stream is allowed, but behavior is defined by the
/// available when the prelude is imported: /// implementation.
/// ///
/// ``` /// # Examples
/// # #[allow(unused_imports)] ///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::io::SeekFrom;
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// ```
/// ///
/// [`std::io::Seek`]: https://doc.rust-lang.org/std/io/trait.Seek.html /// let mut file = File::open("a.txt").await?;
/// [`futures::io::AsyncSeek`]: ///
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncSeek.html /// let file_len = file.seek(SeekFrom::End(0)).await?;
/// [provided methods]: #provided-methods /// #
pub trait Seek { /// # Ok(()) }) }
/// Attempt to seek to an offset, in bytes, in a stream. /// ```
fn poll_seek( fn seek(
self: Pin<&mut Self>, &mut self,
cx: &mut Context<'_>, pos: SeekFrom,
pos: SeekFrom, ) -> impl Future<Output = io::Result<u64>> [SeekFuture<'_, Self>]
) -> Poll<io::Result<u64>>;
/// Seeks to a new position in a byte stream.
///
/// Returns the new position in the byte stream.
///
/// A seek beyond the end of stream is allowed, but behavior is defined by the
/// implementation.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::io::SeekFrom;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let file_len = file.seek(SeekFrom::End(0)).await?;
/// #
/// # Ok(()) }) }
/// ```
fn seek(&mut self, pos: SeekFrom) -> ImplFuture<io::Result<u64>>
where
Self: Unpin
{
unreachable!()
}
}
impl<T: Seek + Unpin + ?Sized> Seek for Box<T> {
fn poll_seek(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>> {
unreachable!()
}
}
impl<T: Seek + Unpin + ?Sized> Seek for &mut T {
fn poll_seek(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>> {
unreachable!()
}
}
impl<P> Seek for Pin<P>
where where
P: DerefMut + Unpin, Self: Unpin,
<P as Deref>::Target: Seek,
{ {
fn poll_seek( SeekFuture { seeker: self, pos }
self: Pin<&mut Self>,
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>> {
unreachable!()
}
} }
} else {
pub use futures_io::AsyncSeek as Seek;
} }
}
#[doc(hidden)] impl<T: Seek + Unpin + ?Sized> Seek for Box<T> {
pub trait SeekExt: futures_io::AsyncSeek { fn poll_seek(
fn seek(&mut self, pos: SeekFrom) -> SeekFuture<'_, Self> self: Pin<&mut Self>,
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>> {
unreachable!()
}
}
impl<T: Seek + Unpin + ?Sized> Seek for &mut T {
fn poll_seek(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>> {
unreachable!()
}
}
impl<P> Seek for Pin<P>
where where
Self: Unpin, P: DerefMut + Unpin,
<P as Deref>::Target: Seek,
{ {
SeekFuture { seeker: self, pos } fn poll_seek(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>> {
unreachable!()
}
} }
} }
impl<T: futures_io::AsyncSeek + ?Sized> SeekExt for T {}
#[doc(hidden)] #[doc(hidden)]
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct SeekFuture<'a, T: Unpin + ?Sized> { pub struct SeekFuture<'a, T: Unpin + ?Sized> {

View file

@ -11,6 +11,7 @@ use write_vectored::WriteVectoredFuture;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use crate::io::IoSlice; use crate::io::IoSlice;
use crate::utils::extension_trait;
cfg_if! { cfg_if! {
if #[cfg(feature = "docs")] { if #[cfg(feature = "docs")] {
@ -19,271 +20,235 @@ cfg_if! {
use crate::io; use crate::io;
use crate::task::{Context, Poll}; use crate::task::{Context, Poll};
}
}
#[doc(hidden)] extension_trait! {
pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); /// Allows writing to a byte stream.
///
/// This trait is a re-export of [`futures::io::AsyncWrite`] and is an async version of
/// [`std::io::Write`].
///
/// Methods other than [`poll_write`], [`poll_write_vectored`], [`poll_flush`], and
/// [`poll_close`] 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::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
/// [`futures::io::AsyncWrite`]:
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncWrite.html
/// [`poll_write`]: #tymethod.poll_write
/// [`poll_write_vectored`]: #method.poll_write_vectored
/// [`poll_flush`]: #tymethod.poll_flush
/// [`poll_close`]: #tymethod.poll_close
pub trait Write [WriteExt: futures_io::AsyncWrite] {
/// Attempt to write bytes from `buf` into the object.
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>>;
/// Allows writing to a byte stream. /// Attempt to write bytes from `bufs` into the object using vectored
/// IO operations.
fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>]
) -> Poll<io::Result<usize>> {
unreachable!()
}
/// Attempt to flush the object, ensuring that any buffered data reach
/// their destination.
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
/// Attempt to close the object.
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
/// Writes some bytes into the byte stream.
/// ///
/// This trait is a re-export of [`futures::io::AsyncWrite`] and is an async version of /// Returns the number of bytes written from the start of the buffer.
/// [`std::io::Write`].
/// ///
/// Methods other than [`poll_write`], [`poll_write_vectored`], [`poll_flush`], and /// If the return value is `Ok(n)` then it must be guaranteed that
/// [`poll_close`] do not really exist in the trait itself, but they become available when /// `0 <= n <= buf.len()`. A return value of `0` typically means that the underlying
/// the prelude is imported: /// object is no longer able to accept bytes and will likely not be able to in the
/// future as well, or that the buffer provided is empty.
/// ///
/// ``` /// # Examples
/// # #[allow(unused_imports)] ///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*; /// use async_std::prelude::*;
///
/// let mut file = File::create("a.txt").await?;
///
/// let n = file.write(b"hello world").await?;
/// #
/// # Ok(()) }) }
/// ```
fn write<'a>(&'a mut self, buf: &'a [u8]) -> impl Future<Output = io::Result<usize>> + 'a [WriteFuture<'a, Self>]
where
Self: Unpin,
{
WriteFuture { writer: self, buf }
}
/// Flushes the stream to ensure that all buffered contents reach their destination.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::create("a.txt").await?;
///
/// file.write_all(b"hello world").await?;
/// file.flush().await?;
/// #
/// # Ok(()) }) }
/// ```
fn flush(&mut self) -> impl Future<Output = io::Result<()>> + '_ [FlushFuture<'_, Self>]
where
Self: Unpin,
{
FlushFuture { writer: self }
}
/// Like [`write`], except that it writes from a slice of buffers.
///
/// Data is copied from each buffer in order, with the final buffer read from possibly
/// being only partially consumed. This method must behave as a call to [`write`] with
/// the buffers concatenated would.
///
/// The default implementation calls [`write`] with either the first nonempty buffer
/// provided, or an empty one if none exists.
///
/// [`write`]: #tymethod.write
fn write_vectored<'a>(
&'a mut self,
bufs: &'a [IoSlice<'a>],
) -> impl Future<Output = io::Result<usize>> + 'a [WriteVectoredFuture<'a, Self>]
where
Self: Unpin,
{
WriteVectoredFuture { writer: self, bufs }
}
/// Writes an entire buffer into the byte stream.
///
/// This method will continuously call [`write`] until there is no more data to be
/// written or an error is returned. This method will not return until the entire
/// buffer has been successfully written or such an error occurs.
///
/// [`write`]: #tymethod.write
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::create("a.txt").await?;
///
/// file.write_all(b"hello world").await?;
/// #
/// # Ok(()) }) }
/// ``` /// ```
/// ///
/// [`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// [`write`]: #tymethod.write
/// [`futures::io::AsyncWrite`]: fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future<Output = io::Result<()>> + 'a [WriteAllFuture<'a, Self>]
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncWrite.html
/// [`poll_write`]: #tymethod.poll_write
/// [`poll_write_vectored`]: #method.poll_write_vectored
/// [`poll_flush`]: #tymethod.poll_flush
/// [`poll_close`]: #tymethod.poll_close
pub trait Write {
/// Attempt to write bytes from `buf` into the object.
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>>;
/// Attempt to write bytes from `bufs` into the object using vectored
/// IO operations.
fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>]
) -> Poll<io::Result<usize>> {
unreachable!()
}
/// Attempt to flush the object, ensuring that any buffered data reach
/// their destination.
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
/// Attempt to close the object.
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
/// Writes some bytes into the byte stream.
///
/// Returns the number of bytes written from the start of the buffer.
///
/// If the return value is `Ok(n)` then it must be guaranteed that
/// `0 <= n <= buf.len()`. A return value of `0` typically means that the underlying
/// object is no longer able to accept bytes and will likely not be able to in the
/// future as well, or that the buffer provided is empty.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::create("a.txt").await?;
///
/// let n = file.write(b"hello world").await?;
/// #
/// # Ok(()) }) }
/// ```
fn write<'a>(&'a mut self, buf: &'a [u8]) -> ImplFuture<'a, io::Result<usize>>
where
Self: Unpin,
{
unreachable!()
}
/// Flushes the stream to ensure that all buffered contents reach their destination.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::create("a.txt").await?;
///
/// file.write_all(b"hello world").await?;
/// file.flush().await?;
/// #
/// # Ok(()) }) }
/// ```
fn flush(&mut self) -> ImplFuture<'_, io::Result<()>>
where
Self: Unpin,
{
unreachable!()
}
/// Like [`write`], except that it writes from a slice of buffers.
///
/// Data is copied from each buffer in order, with the final buffer read from possibly
/// being only partially consumed. This method must behave as a call to [`write`] with
/// the buffers concatenated would.
///
/// The default implementation calls [`write`] with either the first nonempty buffer
/// provided, or an empty one if none exists.
///
/// [`write`]: #tymethod.write
fn write_vectored<'a>(
&'a mut self,
bufs: &'a [IoSlice<'a>],
) -> ImplFuture<'a, io::Result<usize>>
where
Self: Unpin,
{
unreachable!()
}
/// Writes an entire buffer into the byte stream.
///
/// This method will continuously call [`write`] until there is no more data to be
/// written or an error is returned. This method will not return until the entire
/// buffer has been successfully written or such an error occurs.
///
/// [`write`]: #tymethod.write
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::create("a.txt").await?;
///
/// file.write_all(b"hello world").await?;
/// #
/// # Ok(()) }) }
/// ```
///
/// [`write`]: #tymethod.write
fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> ImplFuture<'a, io::Result<()>>
where
Self: Unpin,
{
unreachable!()
}
}
impl<T: Write + Unpin + ?Sized> Write for Box<T> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
}
impl<T: Write + Unpin + ?Sized> Write for &mut T {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
}
impl<P> Write for Pin<P>
where where
P: DerefMut + Unpin, Self: Unpin,
<P as Deref>::Target: Write,
{ {
fn poll_write( WriteAllFuture { writer: self, buf }
self: Pin<&mut Self>, }
cx: &mut Context<'_>, }
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { impl<T: Write + Unpin + ?Sized> Write for Box<T> {
unreachable!() fn poll_write(
} self: Pin<&mut Self>,
cx: &mut Context<'_>,
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { buf: &[u8],
unreachable!() ) -> Poll<io::Result<usize>> {
} unreachable!()
} }
impl Write for Vec<u8> { fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
fn poll_write( unreachable!()
self: Pin<&mut Self>, }
cx: &mut Context<'_>,
buf: &[u8], fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
) -> Poll<io::Result<usize>> { unreachable!()
unreachable!() }
} }
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { impl<T: Write + Unpin + ?Sized> Write for &mut T {
unreachable!() fn poll_write(
} self: Pin<&mut Self>,
cx: &mut Context<'_>,
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { buf: &[u8],
unreachable!() ) -> Poll<io::Result<usize>> {
} unreachable!()
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
}
impl<P> Write for Pin<P>
where
P: DerefMut + Unpin,
<P as Deref>::Target: Write,
{
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
}
impl Write for Vec<u8> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
} }
} else {
pub use futures_io::AsyncWrite as Write;
} }
} }
#[doc(hidden)]
pub trait WriteExt: Write {
fn write<'a>(&'a mut self, buf: &'a [u8]) -> WriteFuture<'a, Self>
where
Self: Unpin,
{
WriteFuture { writer: self, buf }
}
fn flush(&mut self) -> FlushFuture<'_, Self>
where
Self: Unpin,
{
FlushFuture { writer: self }
}
fn write_vectored<'a>(&'a mut self, bufs: &'a [IoSlice<'a>]) -> WriteVectoredFuture<'a, Self>
where
Self: Unpin,
{
WriteVectoredFuture { writer: self, bufs }
}
fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> WriteAllFuture<'a, Self>
where
Self: Unpin,
{
WriteAllFuture { writer: self, buf }
}
}
impl<T: Write + ?Sized> WriteExt for T {}

View file

@ -46,6 +46,7 @@
#![doc(test(attr(deny(rust_2018_idioms, warnings))))] #![doc(test(attr(deny(rust_2018_idioms, warnings))))]
#![doc(test(attr(allow(unused_extern_crates, unused_variables))))] #![doc(test(attr(allow(unused_extern_crates, unused_variables))))]
#![doc(html_logo_url = "https://async.rs/images/logo--hero.svg")] #![doc(html_logo_url = "https://async.rs/images/logo--hero.svg")]
#![recursion_limit = "1024"]
use cfg_if::cfg_if; use cfg_if::cfg_if;

File diff suppressed because it is too large Load diff

View file

@ -19,3 +19,89 @@ pub fn abort_on_panic<T>(f: impl FnOnce() -> T) -> T {
mem::forget(bomb); mem::forget(bomb);
t t
} }
#[doc(hidden)]
#[macro_export]
macro_rules! extension_trait {
(@gen ($($head:tt)*) pub trait $name:ident [$ext:ident: $orig:path] { $($body:tt)* } $($imp:item)*) => {
#[allow(dead_code)]
mod owned {
#[doc(hidden)]
pub struct ImplFuture<T>(std::marker::PhantomData<T>);
}
#[allow(dead_code)]
mod borrowed {
#[doc(hidden)]
pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>);
}
#[cfg(feature = "docs")]
$($head)* pub trait $name {
extension_trait!(@doc () $($body)*);
}
#[cfg(not(feature = "docs"))]
pub use $orig as $name;
$($head)* pub trait $ext: $orig {
extension_trait!(@ext () $($body)*);
}
impl<T: $orig + ?Sized> $ext for T {}
$(#[cfg(feature = "docs")] $imp)*
};
(@gen ($($head:tt)*) $token:tt $($tail:tt)*) => {
extension_trait!(@gen ($($head)* $token) $($tail)*);
};
(@doc ($($head:tt)*) fn $name:ident $args:tt $(-> $ret:ty)?; $($tail:tt)*) => {
extension_trait!(@doc ($($head)* fn $name $args $(-> $ret)?;) $($tail)*);
};
(@ext ($($head:tt)*) fn $name:ident $args:tt $(-> $ret:ty)?; $($tail:tt)*) => {
extension_trait!(@ext ($($head)*) $($tail)*);
};
(@doc ($($head:tt)*) fn $name:ident $args:tt $(-> $ret:ty)? { $($body:tt)* } $($tail:tt)*) => {
extension_trait!(@doc ($($head)* fn $name $args $(-> $ret)? { $($body)* }) $($tail)*);
};
(@ext ($($head:tt)*) fn $name:ident $args:tt $(-> $ret:ty)? { $($body:tt)* } $($tail:tt)*) => {
extension_trait!(@ext ($($head)*) $($tail)*);
};
(@doc ($($head:tt)*) type $name:ident; $($tail:tt)*) => {
extension_trait!(@doc ($($head)* type $name;) $($tail)*);
};
(@ext ($($head:tt)*) type $ident:ty; $($tail:tt)*) => {
extension_trait!(@ext ($($head)*) $($tail)*);
};
(@doc ($($head:tt)*) -> impl Future<Output = $out:ty> [$f:ty] $($tail:tt)*) => {
extension_trait!(@doc ($($head)* -> owned::ImplFuture<$out>) $($tail)*);
};
(@ext ($($head:tt)*) -> impl Future<Output = $out:ty> [$f:ty] $($tail:tt)*) => {
extension_trait!(@ext ($($head)* -> $f) $($tail)*);
};
(@doc ($($head:tt)*) -> impl Future<Output = $out:ty> + $lt:lifetime [$f:ty] $($tail:tt)*) => {
extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$lt, $out>) $($tail)*);
};
(@ext ($($head:tt)*) -> impl Future<Output = $out:ty> + $lt:lifetime [$f:ty] $($tail:tt)*) => {
extension_trait!(@ext ($($head)* -> $f) $($tail)*);
};
(@doc ($($head:tt)*) $token:tt $($tail:tt)*) => {
extension_trait!(@doc ($($head)* $token) $($tail)*);
};
(@ext ($($head:tt)*) $token:tt $($tail:tt)*) => {
extension_trait!(@ext ($($head)* $token) $($tail)*);
};
(@doc ($($head:tt)*)) => { $($head)* };
(@ext ($($head:tt)*)) => { $($head)* };
($($head:tt)*) => { extension_trait!(@gen () $($head)*); };
}
pub use crate::extension_trait;