From 79eab9eb9a6aa92e52372421b154ceeb443c9cca Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 26 Sep 2019 07:46:29 -0400 Subject: [PATCH 1/4] Simplify extension traits using a macro --- src/io/buf_read/mod.rs | 484 +++++----- src/io/read/mod.rs | 522 +++++----- src/io/seek.rs | 173 ++-- src/io/write/mod.rs | 469 +++++---- src/lib.rs | 1 + src/stream/stream/mod.rs | 1985 ++++++++++++++++++-------------------- src/utils.rs | 86 ++ 7 files changed, 1780 insertions(+), 1940 deletions(-) diff --git a/src/io/buf_read/mod.rs b/src/io/buf_read/mod.rs index fa8e9eb..ad8df85 100644 --- a/src/io/buf_read/mod.rs +++ b/src/io/buf_read/mod.rs @@ -13,294 +13,266 @@ use cfg_if::cfg_if; use crate::io; use crate::task::{Context, Poll}; +use crate::utils::extension_trait; cfg_if! { if #[cfg(feature = "docs")] { use std::ops::{Deref, DerefMut}; + } +} - #[doc(hidden)] - pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); +extension_trait! { + /// 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>; - /// 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 - /// [`std::io::BufRead`]. + /// 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`. /// - /// The [provided methods] do not really exist in the trait itself, but they become - /// available when the prelude is imported: + /// If successful, this function will return the total number of bytes read. /// - /// ``` - /// # #[allow(unused_imports)] + /// # 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(()) }) } /// ``` /// - /// [`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>; - - /// 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, - ) -> ImplFuture<'a, io::Result> - 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> - 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 - where - Self: Unpin + Sized, - { - unreachable!() - } - } - - impl BufRead for Box { - fn poll_fill_buf( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - unreachable!() - } - - fn consume(self: Pin<&mut Self>, amt: usize) { - unreachable!() - } - } - - impl BufRead for &mut T { - fn poll_fill_buf( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - unreachable!() - } - - fn consume(self: Pin<&mut Self>, amt: usize) { - unreachable!() - } - } - - impl

BufRead for Pin

+ /// 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 - P: DerefMut + Unpin, -

::Target: BufRead, + Self: Unpin, { - fn poll_fill_buf( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - unreachable!() - } - - fn consume(self: Pin<&mut Self>, amt: usize) { - unreachable!() + ReadUntilFuture { + reader: self, + byte, + buf, + read: 0, } } - 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!() + /// 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, } } - } else { - pub use futures_io::AsyncBufRead as BufRead; - } -} -#[doc(hidden)] -pub trait BufReadExt: futures_io::AsyncBufRead { - fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec) -> ReadUntilFuture<'a, Self> - where - Self: Unpin, - { - ReadUntilFuture { - reader: self, - byte, - buf, - read: 0, + /// 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, + } } } - fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLineFuture<'a, Self> - where - Self: Unpin, - { - ReadLineFuture { - reader: self, - bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) }, - buf, - read: 0, + impl BufRead for Box { + fn poll_fill_buf( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + unreachable!() + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + unreachable!() } } - fn lines(self) -> Lines + impl BufRead for &mut T { + fn poll_fill_buf( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + unreachable!() + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + unreachable!() + } + } + + impl

BufRead for Pin

where - Self: Unpin + Sized, + P: DerefMut + Unpin, +

::Target: BufRead, { - Lines { - reader: self, - buf: String::new(), - bytes: Vec::new(), - read: 0, + fn poll_fill_buf( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + 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> { + unreachable!() + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + unreachable!() } } } -impl BufReadExt for T {} - pub fn read_until_internal( mut reader: Pin<&mut R>, cx: &mut Context<'_>, diff --git a/src/io/read/mod.rs b/src/io/read/mod.rs index 1983823..3acfc28 100644 --- a/src/io/read/mod.rs +++ b/src/io/read/mod.rs @@ -11,10 +11,10 @@ use read_to_string::ReadToStringFuture; use read_vectored::ReadVectoredFuture; use std::mem; - use cfg_if::cfg_if; use crate::io::IoSliceMut; +use crate::utils::extension_trait; cfg_if! { if #[cfg(feature = "docs")] { @@ -23,311 +23,265 @@ cfg_if! { use crate::io; use crate::task::{Context, Poll}; + } +} - #[doc(hidden)] - pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); +extension_trait! { + /// 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>; - /// 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> { + unreachable!() + } + + /// Reads some bytes from the byte stream. /// - /// This trait is a re-export of [`futures::io::AsyncRead`] and is an async version of - /// [`std::io::Read`]. + /// Returns the number of bytes read from the start of the buffer. /// - /// 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: + /// 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: /// - /// ``` - /// # #[allow(unused_imports)] + /// 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::*; - /// ``` /// - /// [`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 { - /// Attempt to read from the `AsyncRead` into `buf`. - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll>; - - /// 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> { - 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> - 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> - 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, - ) -> ImplFuture<'a, io::Result> - 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> - 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 Read for Box { - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - unreachable!() - } - } - - impl Read for &mut T { - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - unreachable!() - } - } - - impl

Read for Pin

+ /// 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]) -> impl Future> + 'a [ReadFuture<'a, Self>] where - P: DerefMut + Unpin, -

::Target: Read, + Self: Unpin { - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - unreachable!() + ReadFuture { reader: self, buf } + } + + /// 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>], + ) -> impl Future> + '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, + ) -> impl Future> + 'a [ReadToEndFuture<'a, Self>] + where + Self: Unpin, + { + let start_len = buf.len(); + ReadToEndFuture { + reader: self, + buf, + start_len, } } - impl Read for &[u8] { - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - 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, + ) -> impl Future> + '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)] -pub trait ReadExt: futures_io::AsyncRead { - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadFuture<'a, Self> - where - Self: Unpin, - { - ReadFuture { reader: self, buf } - } - - fn read_vectored<'a>( - &'a mut self, - bufs: &'a mut [IoSliceMut<'a>], - ) -> ReadVectoredFuture<'a, Self> - where - Self: Unpin, - { - ReadVectoredFuture { reader: self, bufs } - } - - fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec) -> ReadToEndFuture<'a, Self> - where - Self: Unpin, - { - let start_len = buf.len(); - ReadToEndFuture { - reader: self, - buf, - start_len, + /// 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]) -> impl Future> + '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> - where - Self: Unpin, - { - let start_len = buf.len(); - ReadToStringFuture { - reader: self, - bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) }, - buf, - start_len, + impl Read for Box { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + unreachable!() } } - fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExactFuture<'a, Self> + impl Read for &mut T { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + unreachable!() + } + } + + impl

Read for Pin

where - Self: Unpin, + P: DerefMut + Unpin, +

::Target: Read, { - ReadExactFuture { reader: self, buf } + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + unreachable!() + } + } + + impl Read for &[u8] { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + unreachable!() + } } } - -impl ReadExt for T {} diff --git a/src/io/seek.rs b/src/io/seek.rs index f2dd4d9..a9234f9 100644 --- a/src/io/seek.rs +++ b/src/io/seek.rs @@ -5,119 +5,108 @@ use cfg_if::cfg_if; use crate::future::Future; use crate::io::{self, SeekFrom}; use crate::task::{Context, Poll}; +use crate::utils::extension_trait; cfg_if! { if #[cfg(feature = "docs")] { use std::ops::{Deref, DerefMut}; + } +} - #[doc(hidden)] - pub struct ImplFuture(std::marker::PhantomData); +extension_trait! { + /// 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>; - /// 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 - /// [`std::io::Seek`]. + /// Returns the new position in the byte stream. /// - /// The [provided methods] do not really exist in the trait itself, but they become - /// available when the prelude is imported: + /// A seek beyond the end of stream is allowed, but behavior is defined by the + /// implementation. /// - /// ``` - /// # #[allow(unused_imports)] + /// # 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::*; - /// ``` /// - /// [`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 { - /// Attempt to seek to an offset, in bytes, in a stream. - fn poll_seek( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - pos: SeekFrom, - ) -> Poll>; - - /// 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> - where - Self: Unpin - { - unreachable!() - } - } - - impl Seek for Box { - fn poll_seek( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - pos: SeekFrom, - ) -> Poll> { - unreachable!() - } - } - - impl Seek for &mut T { - fn poll_seek( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - pos: SeekFrom, - ) -> Poll> { - unreachable!() - } - } - - impl

Seek for Pin

+ /// let mut file = File::open("a.txt").await?; + /// + /// let file_len = file.seek(SeekFrom::End(0)).await?; + /// # + /// # Ok(()) }) } + /// ``` + fn seek( + &mut self, + pos: SeekFrom, + ) -> impl Future> [SeekFuture<'_, Self>] where - P: DerefMut + Unpin, -

::Target: Seek, + Self: Unpin, { - fn poll_seek( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - pos: SeekFrom, - ) -> Poll> { - unreachable!() - } + SeekFuture { seeker: self, pos } } - } else { - pub use futures_io::AsyncSeek as Seek; } -} -#[doc(hidden)] -pub trait SeekExt: futures_io::AsyncSeek { - fn seek(&mut self, pos: SeekFrom) -> SeekFuture<'_, Self> + impl Seek for Box { + fn poll_seek( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + unreachable!() + } + } + + impl Seek for &mut T { + fn poll_seek( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + unreachable!() + } + } + + impl

Seek for Pin

where - Self: Unpin, + P: DerefMut + Unpin, +

::Target: Seek, { - SeekFuture { seeker: self, pos } + fn poll_seek( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + unreachable!() + } } } -impl SeekExt for T {} - #[doc(hidden)] #[allow(missing_debug_implementations)] pub struct SeekFuture<'a, T: Unpin + ?Sized> { diff --git a/src/io/write/mod.rs b/src/io/write/mod.rs index f5f1602..27e7920 100644 --- a/src/io/write/mod.rs +++ b/src/io/write/mod.rs @@ -11,6 +11,7 @@ use write_vectored::WriteVectoredFuture; use cfg_if::cfg_if; use crate::io::IoSlice; +use crate::utils::extension_trait; cfg_if! { if #[cfg(feature = "docs")] { @@ -19,271 +20,235 @@ cfg_if! { use crate::io; use crate::task::{Context, Poll}; + } +} - #[doc(hidden)] - pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); +extension_trait! { + /// 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>; - /// 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> { + 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>; + + /// Attempt to close the object. + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + + /// Writes some bytes into the byte stream. /// - /// This trait is a re-export of [`futures::io::AsyncWrite`] and is an async version of - /// [`std::io::Write`]. + /// Returns the number of bytes written from the start of the buffer. /// - /// 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: + /// 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. /// - /// ``` - /// # #[allow(unused_imports)] + /// # 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]) -> impl Future> + '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> + '_ [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> + '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 - /// [`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 { - /// Attempt to write bytes from `buf` into the object. - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll>; - - /// 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> { - 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>; - - /// Attempt to close the object. - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; - - /// 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> - 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> - 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 Write for Box { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - unreachable!() - } - - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - } - - impl Write for &mut T { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - unreachable!() - } - - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - } - - impl

Write for Pin

+ /// [`write`]: #tymethod.write + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + 'a [WriteAllFuture<'a, Self>] where - P: DerefMut + Unpin, -

::Target: Write, + Self: Unpin, { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - unreachable!() - } + WriteAllFuture { writer: self, buf } + } + } - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } + impl Write for Box { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + unreachable!() } - impl Write for Vec { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - unreachable!() - } - - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + } + + impl Write for &mut T { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + unreachable!() + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + } + + impl

Write for Pin

+ where + P: DerefMut + Unpin, +

::Target: Write, + { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + unreachable!() + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + } + + impl Write for Vec { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + unreachable!() + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + 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 WriteExt for T {} diff --git a/src/lib.rs b/src/lib.rs index 31635ef..f188a68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,6 +46,7 @@ #![doc(test(attr(deny(rust_2018_idioms, warnings))))] #![doc(test(attr(allow(unused_extern_crates, unused_variables))))] #![doc(html_logo_url = "https://async.rs/images/logo--hero.svg")] +#![recursion_limit = "1024"] use cfg_if::cfg_if; diff --git a/src/stream/stream/mod.rs b/src/stream/stream/mod.rs index 0348b6a..ba23718 100644 --- a/src/stream/stream/mod.rs +++ b/src/stream/stream/mod.rs @@ -69,6 +69,16 @@ use std::marker::PhantomData; use cfg_if::cfg_if; +use crate::utils::extension_trait; + +cfg_if! { + if #[cfg(feature = "docs")] { + use std::ops::{Deref, DerefMut}; + + use crate::task::{Context, Poll}; + } +} + cfg_if! { if #[cfg(any(feature = "unstable", feature = "docs"))] { use std::pin::Pin; @@ -78,1089 +88,952 @@ cfg_if! { } } -cfg_if! { - if #[cfg(feature = "docs")] { - use std::ops::{Deref, DerefMut}; +extension_trait! { + /// An asynchronous stream of values. + /// + /// This trait is a re-export of [`futures::stream::Stream`] and is an async version of + /// [`std::iter::Iterator`]. + /// + /// 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::iter::Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html + /// [`futures::stream::Stream`]: + /// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/stream/trait.Stream.html + /// [provided methods]: #provided-methods + pub trait Stream [StreamExt: futures_core::stream::Stream] { + /// The type of items yielded by this stream. + type Item; - use crate::task::{Context, Poll}; + #[doc = r#" + Attempts to receive the next item from the stream. - #[doc(hidden)] - pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); + There are several possible return values: - /// An asynchronous stream of values. - /// - /// This trait is a re-export of [`futures::stream::Stream`] and is an async version of - /// [`std::iter::Iterator`]. - /// - /// 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::iter::Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html - /// [`futures::stream::Stream`]: - /// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/stream/trait.Stream.html - /// [provided methods]: #provided-methods - pub trait Stream { - /// The type of items yielded by this stream. - type Item; + * `Poll::Pending` means this stream's next value is not ready yet. + * `Poll::Ready(None)` means this stream has been exhausted. + * `Poll::Ready(Some(item))` means `item` was received out of the stream. - /// Attempts to receive the next item from the stream. - /// - /// There are several possible return values: - /// - /// * `Poll::Pending` means this stream's next value is not ready yet. - /// * `Poll::Ready(None)` means this stream has been exhausted. - /// * `Poll::Ready(Some(item))` means `item` was received out of the stream. - /// - /// # Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::pin::Pin; - /// - /// use async_std::prelude::*; - /// use async_std::stream; - /// use async_std::task::{Context, Poll}; - /// - /// fn increment( - /// s: impl Stream + Unpin, - /// ) -> impl Stream + Unpin { - /// struct Increment(S); - /// - /// impl + Unpin> Stream for Increment { - /// type Item = S::Item; - /// - /// fn poll_next( - /// mut self: Pin<&mut Self>, - /// cx: &mut Context<'_>, - /// ) -> Poll> { - /// match Pin::new(&mut self.0).poll_next(cx) { - /// Poll::Pending => Poll::Pending, - /// Poll::Ready(None) => Poll::Ready(None), - /// Poll::Ready(Some(item)) => Poll::Ready(Some(item + 1)), - /// } - /// } - /// } - /// - /// Increment(s) - /// } - /// - /// let mut s = increment(stream::once(7)); - /// - /// assert_eq!(s.next().await, Some(8)); - /// assert_eq!(s.next().await, None); - /// # - /// # }) } - /// ``` - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + # Examples - /// Advances the stream and returns the next value. - /// - /// Returns [`None`] when iteration is finished. Individual stream implementations may - /// choose to resume iteration, and so calling `next()` again may or may not eventually - /// start returning more values. - /// - /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use async_std::stream; - /// - /// let mut s = stream::once(7); - /// - /// assert_eq!(s.next().await, Some(7)); - /// assert_eq!(s.next().await, None); - /// # - /// # }) } - /// ``` - fn next(&mut self) -> ImplFuture<'_, Option> - where - Self: Unpin, - { - unreachable!() + ``` + # fn main() { async_std::task::block_on(async { + # + use std::pin::Pin; + + use async_std::prelude::*; + use async_std::stream; + use async_std::task::{Context, Poll}; + + fn increment( + s: impl Stream + Unpin, + ) -> impl Stream + Unpin { + struct Increment(S); + + impl + Unpin> Stream for Increment { + type Item = S::Item; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + match Pin::new(&mut self.0).poll_next(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(None) => Poll::Ready(None), + Poll::Ready(Some(item)) => Poll::Ready(Some(item + 1)), + } + } + } + + Increment(s) } - /// Creates a stream that yields its first `n` elements. - /// - /// # Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use async_std::stream; - /// - /// let mut s = stream::repeat(9).take(3); - /// - /// while let Some(v) = s.next().await { - /// assert_eq!(v, 9); - /// } - /// # - /// # }) } - /// ``` - fn take(self, n: usize) -> Take - where - Self: Sized, - { - unreachable!() - } + let mut s = increment(stream::once(7)); - /// Creates a stream that yields each `step`th element. - /// - /// # Panics - /// - /// This method will panic if the given step is `0`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use std::collections::VecDeque; - /// - /// let s: VecDeque<_> = vec![0u8, 1, 2, 3, 4].into_iter().collect(); - /// let mut stepped = s.step_by(2); - /// - /// assert_eq!(stepped.next().await, Some(0)); - /// assert_eq!(stepped.next().await, Some(2)); - /// assert_eq!(stepped.next().await, Some(4)); - /// assert_eq!(stepped.next().await, None); - /// - /// # - /// # }) } - /// ``` - fn step_by(self, step: usize) -> StepBy - where - Self: Sized, - { - unreachable!() - } + assert_eq!(s.next().await, Some(8)); + assert_eq!(s.next().await, None); + # + # }) } + ``` + "#] + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; - /// Takes two streams and creates a new stream over both in sequence. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use std::collections::VecDeque; - /// - /// let first: VecDeque<_> = vec![0u8, 1].into_iter().collect(); - /// let second: VecDeque<_> = vec![2, 3].into_iter().collect(); - /// let mut c = first.chain(second); - /// - /// assert_eq!(c.next().await, Some(0)); - /// assert_eq!(c.next().await, Some(1)); - /// assert_eq!(c.next().await, Some(2)); - /// assert_eq!(c.next().await, Some(3)); - /// assert_eq!(c.next().await, None); - /// - /// # - /// # }) } - /// ``` - fn chain(self, other: U) -> Chain - where - Self: Sized, - U: Stream + Sized, - { - unreachable!() - } + #[doc = r#" + Advances the stream and returns the next value. - /// Creates a stream that gives the current element's count as well as the next value. - /// - /// # Overflow behaviour. - /// - /// This combinator does no guarding against overflows. - /// - /// # Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use std::collections::VecDeque; - /// - /// let s: VecDeque<_> = vec!['a', 'b', 'c'].into_iter().collect(); - /// let mut s = s.enumerate(); - /// - /// assert_eq!(s.next().await, Some((0, 'a'))); - /// assert_eq!(s.next().await, Some((1, 'b'))); - /// assert_eq!(s.next().await, Some((2, 'c'))); - /// assert_eq!(s.next().await, None); - /// - /// # - /// # }) } - /// ``` - fn enumerate(self) -> Enumerate - where - Self: Sized, - { - unreachable!() - } + Returns [`None`] when iteration is finished. Individual stream implementations may + choose to resume iteration, and so calling `next()` again may or may not eventually + start returning more values. - /// A combinator that does something with each element in the stream, passing the value - /// on. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use std::collections::VecDeque; - /// - /// let a: VecDeque<_> = vec![1u8, 2, 3, 4, 5].into_iter().collect(); - /// let sum = a - /// .inspect(|x| println!("about to filter {}", x)) - /// .filter(|x| x % 2 == 0) - /// .inspect(|x| println!("made it through filter: {}", x)) - /// .fold(0, |sum, i| sum + i).await; - /// - /// assert_eq!(sum, 6); - /// # - /// # }) } - /// ``` - fn inspect(self, f: F) -> Inspect - where - Self: Sized, - F: FnMut(&Self::Item), - { - unreachable!() - } + [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None - /// Transforms this `Stream` into a "fused" `Stream` such that after the first time - /// `poll` returns `Poll::Ready(None)`, all future calls to `poll` will also return - /// `Poll::Ready(None)`. - /// - /// # Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use async_std::stream; - /// - /// let mut s = stream::once(1).fuse(); - /// assert_eq!(s.next().await, Some(1)); - /// assert_eq!(s.next().await, None); - /// assert_eq!(s.next().await, None); - /// # - /// # }) } - /// ``` - fn fuse(self) -> Fuse - where - Self: Sized, - { - unreachable!() - } + # Examples - /// Creates a stream that uses a predicate to determine if an element should be yielded. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let s: VecDeque = vec![1, 2, 3, 4].into_iter().collect(); - /// let mut s = s.filter(|i| i % 2 == 0); - /// - /// assert_eq!(s.next().await, Some(2)); - /// assert_eq!(s.next().await, Some(4)); - /// assert_eq!(s.next().await, None); - /// # - /// # }) } - /// ``` - fn filter

(self, predicate: P) -> Filter - where - Self: Sized, - P: FnMut(&Self::Item) -> bool, - { - unreachable!() - } + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use async_std::stream; - /// Both filters and maps a stream. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let s: VecDeque<&str> = vec!["1", "lol", "3", "NaN", "5"].into_iter().collect(); - /// - /// let mut parsed = s.filter_map(|a| a.parse::().ok()); - /// - /// let one = parsed.next().await; - /// assert_eq!(one, Some(1)); - /// - /// let three = parsed.next().await; - /// assert_eq!(three, Some(3)); - /// - /// let five = parsed.next().await; - /// assert_eq!(five, Some(5)); - /// - /// let end = parsed.next().await; - /// assert_eq!(end, None); - /// # - /// # }) } - /// ``` - fn filter_map(self, f: F) -> FilterMap - where - Self: Sized, - F: FnMut(Self::Item) -> Option, - { - unreachable!() - } + let mut s = stream::once(7); - /// Returns the element that gives the minimum value with respect to the - /// specified comparison function. If several elements are equally minimum, - /// the first element is returned. If the stream is empty, `None` is returned. - /// - /// # Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// - /// let min = Stream::min_by(s.clone(), |x, y| x.cmp(y)).await; - /// assert_eq!(min, Some(1)); - /// - /// let min = Stream::min_by(s, |x, y| y.cmp(x)).await; - /// assert_eq!(min, Some(3)); - /// - /// let min = Stream::min_by(VecDeque::::new(), |x, y| x.cmp(y)).await; - /// assert_eq!(min, None); - /// # - /// # }) } - /// ``` - fn min_by(self, compare: F) -> ImplFuture<'static, Option> - where - Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Ordering, - { - unreachable!() - } - - /// Returns the nth element of the stream. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// - /// let second = s.nth(1).await; - /// assert_eq!(second, Some(2)); - /// # - /// # }) } - /// ``` - /// Calling `nth()` multiple times: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// - /// let second = s.nth(0).await; - /// assert_eq!(second, Some(1)); - /// - /// let second = s.nth(0).await; - /// assert_eq!(second, Some(2)); - /// # - /// # }) } - /// ``` - /// Returning `None` if the stream finished before returning `n` elements: - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// - /// let fourth = s.nth(4).await; - /// assert_eq!(fourth, None); - /// # - /// # }) } - /// ``` - fn nth(&mut self, n: usize) -> ImplFuture<'_, Option> - where - Self: Sized, - { - unreachable!() - } - - /// Tests if every element of the stream matches a predicate. - /// - /// `all()` takes a closure that returns `true` or `false`. It applies - /// this closure to each element of the stream, and if they all return - /// `true`, then so does `all()`. If any of them return `false`, it - /// returns `false`. - /// - /// `all()` is short-circuiting; in other words, it will stop processing - /// as soon as it finds a `false`, given that no matter what else happens, - /// the result will also be `false`. - /// - /// An empty stream returns `true`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use async_std::stream; - /// - /// let mut s = stream::repeat::(42).take(3); - /// assert!(s.all(|x| x == 42).await); - /// - /// # - /// # }) } - /// ``` - /// - /// Empty stream: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use async_std::stream; - /// - /// let mut s = stream::empty::(); - /// assert!(s.all(|_| false).await); - /// # - /// # }) } - /// ``` - #[inline] - fn all(&mut self, f: F) -> ImplFuture<'_, bool> - where - Self: Unpin + Sized, - F: FnMut(Self::Item) -> bool, - { - unreachable!() - } - - /// Searches for an element in a stream that satisfies a predicate. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use std::collections::VecDeque; - /// - /// let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// let res = s.find(|x| *x == 2).await; - /// assert_eq!(res, Some(2)); - /// # - /// # }) } - /// ``` - /// - /// Resuming after a first find: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use std::collections::VecDeque; - /// - /// let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// let res = s.find(|x| *x == 2).await; - /// assert_eq!(res, Some(2)); - /// - /// let next = s.next().await; - /// assert_eq!(next, Some(3)); - /// # - /// # }) } - /// ``` - fn find

(&mut self, p: P) -> ImplFuture<'_, Option> - where - Self: Sized, - P: FnMut(&Self::Item) -> bool, - { - unreachable!() - } - - /// Applies function to the elements of stream and returns the first non-none result. - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use std::collections::VecDeque; - /// - /// let mut s: VecDeque<&str> = vec!["lol", "NaN", "2", "5"].into_iter().collect(); - /// let first_number = s.find_map(|s| s.parse().ok()).await; - /// - /// assert_eq!(first_number, Some(2)); - /// # - /// # }) } - /// ``` - fn find_map(&mut self, f: F) -> ImplFuture<'_, Option> - where - Self: Sized, - F: FnMut(Self::Item) -> Option, - { - unreachable!() - } - - /// A combinator that applies a function to every element in a stream - /// producing a single, final value. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use std::collections::VecDeque; - /// - /// let s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// let sum = s.fold(0, |acc, x| acc + x).await; - /// - /// assert_eq!(sum, 6); - /// # - /// # }) } - /// ``` - fn fold(self, init: B, f: F) -> ImplFuture<'static, B> - where - Self: Sized, - F: FnMut(B, Self::Item) -> B, - { - unreachable!() - } - - /// Tests if any element of the stream matches a predicate. - /// - /// `any()` takes a closure that returns `true` or `false`. It applies - /// this closure to each element of the stream, and if any of them return - /// `true`, then so does `any()`. If they all return `false`, it - /// returns `false`. - /// - /// `any()` is short-circuiting; in other words, it will stop processing - /// as soon as it finds a `true`, given that no matter what else happens, - /// the result will also be `true`. - /// - /// An empty stream returns `false`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use async_std::stream; - /// - /// let mut s = stream::repeat::(42).take(3); - /// assert!(s.any(|x| x == 42).await); - /// # - /// # }) } - /// ``` - /// - /// Empty stream: - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use async_std::stream; - /// - /// let mut s = stream::empty::(); - /// assert!(!s.any(|_| false).await); - /// # - /// # }) } - /// ``` - #[inline] - fn any(&mut self, f: F) -> ImplFuture<'_, bool> - where - Self: Unpin + Sized, - F: FnMut(Self::Item) -> bool, - { - unreachable!() - } - - /// A stream adaptor similar to [`fold`] that holds internal state and produces a new - /// stream. - /// - /// [`fold`]: #method.fold - /// - /// `scan()` takes two arguments: an initial value which seeds the internal state, and - /// a closure with two arguments, the first being a mutable reference to the internal - /// state and the second a stream element. The closure can assign to the internal state - /// to share state between iterations. - /// - /// On iteration, the closure will be applied to each element of the stream and the - /// return value from the closure, an `Option`, is yielded by the stream. - /// - /// ## Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// let mut s = s.scan(1, |state, x| { - /// *state = *state * x; - /// Some(-*state) - /// }); - /// - /// assert_eq!(s.next().await, Some(-1)); - /// assert_eq!(s.next().await, Some(-2)); - /// assert_eq!(s.next().await, Some(-6)); - /// assert_eq!(s.next().await, None); - /// # - /// # }) } - /// ``` - #[inline] - fn scan(self, initial_state: St, f: F) -> Scan - where - Self: Sized, - F: FnMut(&mut St, Self::Item) -> Option, - { - unreachable!() - } - - /// Combinator that `skip`s elements based on a predicate. - /// - /// Takes a closure argument. It will call this closure on every element in - /// the stream and ignore elements until it returns `false`. - /// - /// After `false` is returned, `SkipWhile`'s job is over and all further - /// elements in the strem are yielded. - /// - /// ## Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let a: VecDeque<_> = vec![-1i32, 0, 1].into_iter().collect(); - /// let mut s = a.skip_while(|x| x.is_negative()); - /// - /// assert_eq!(s.next().await, Some(0)); - /// assert_eq!(s.next().await, Some(1)); - /// assert_eq!(s.next().await, None); - /// # - /// # }) } - /// ``` - fn skip_while

(self, predicate: P) -> SkipWhile - where - Self: Sized, - P: FnMut(&Self::Item) -> bool, - { - unreachable!() - } - - /// Creates a combinator that skips the first `n` elements. - /// - /// ## Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// let s: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// let mut skipped = s.skip(2); - /// - /// assert_eq!(skipped.next().await, Some(3)); - /// assert_eq!(skipped.next().await, None); - /// # - /// # }) } - /// ``` - fn skip(self, n: usize) -> Skip - where - Self: Sized, - { - unreachable!() - } - - /// 'Zips up' two streams into a single stream of pairs. - /// - /// `zip()` returns a new stream that will iterate over two other streams, returning a - /// tuple where the first element comes from the first stream, and the second element - /// comes from the second stream. - /// - /// In other words, it zips two streams together, into a single one. - /// - /// If either stream returns [`None`], [`poll_next`] from the zipped stream will return - /// [`None`]. If the first stream returns [`None`], `zip` will short-circuit and - /// `poll_next` will not be called on the second stream. - /// - /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None - /// [`poll_next`]: #tymethod.poll_next - /// - /// ## Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use std::collections::VecDeque; - /// use async_std::stream::Stream; - /// - /// let l: VecDeque = vec![1, 2, 3].into_iter().collect(); - /// let r: VecDeque = vec![4, 5, 6, 7].into_iter().collect(); - /// let mut s = l.zip(r); - /// - /// assert_eq!(s.next().await, Some((1, 4))); - /// assert_eq!(s.next().await, Some((2, 5))); - /// assert_eq!(s.next().await, Some((3, 6))); - /// assert_eq!(s.next().await, None); - /// # - /// # }) } - /// ``` - #[inline] - fn zip(self, other: U) -> Zip - where - Self: Sized, - U: Stream, - { - unreachable!() - } - - /// Transforms a stream into a collection. - /// - /// `collect()` can take anything streamable, and turn it into a relevant - /// collection. This is one of the more powerful methods in the async - /// standard library, used in a variety of contexts. - /// - /// The most basic pattern in which `collect()` is used is to turn one - /// collection into another. You take a collection, call [`stream`] on it, - /// do a bunch of transformations, and then `collect()` at the end. - /// - /// Because `collect()` is so general, it can cause problems with type - /// inference. As such, `collect()` is one of the few times you'll see - /// the syntax affectionately known as the 'turbofish': `::<>`. This - /// helps the inference algorithm understand specifically which collection - /// you're trying to collect into. - /// - /// # Examples - /// - /// ``` - /// # fn main() { async_std::task::block_on(async { - /// # - /// use async_std::prelude::*; - /// use async_std::stream; - /// - /// let s = stream::repeat(9u8).take(3); - /// let buf: Vec = s.collect().await; - /// - /// assert_eq!(buf, vec![9; 3]); - /// - /// // You can also collect streams of Result values - /// // into any collection that implements FromStream - /// let s = stream::repeat(Ok(9)).take(3); - /// // We are using Vec here, but other collections - /// // are supported as well - /// let buf: Result, ()> = s.collect().await; - /// - /// assert_eq!(buf, Ok(vec![9; 3])); - /// - /// // The stream will stop on the first Err and - /// // return that instead - /// let s = stream::repeat(Err(5)).take(3); - /// let buf: Result, u8> = s.collect().await; - /// - /// assert_eq!(buf, Err(5)); - /// # - /// # }) } - /// ``` - /// - /// [`stream`]: trait.Stream.html#tymethod.next - #[cfg(any(feature = "unstable", feature = "docs"))] - #[cfg_attr(feature = "docs", doc(cfg(unstable)))] - #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead (TODO)"] - fn collect<'a, B>(self) -> ImplFuture<'a, B> - where - Self: Sized + 'a, - B: FromStream, - { - unreachable!() - } - } - - impl Stream for Box { - type Item = S::Item; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - } - - impl Stream for &mut S { - type Item = S::Item; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - } - - impl

Stream for Pin

+ assert_eq!(s.next().await, Some(7)); + assert_eq!(s.next().await, None); + # + # }) } + ``` + "#] + fn next(&mut self) -> impl Future> + '_ [NextFuture<'_, Self>] where - P: DerefMut + Unpin, -

::Target: Stream, + Self: Unpin, { - type Item = <

::Target as Stream>::Item; + NextFuture { stream: self } + } - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + #[doc = r#" + Creates a stream that yields its first `n` elements. + + # Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use async_std::stream; + + let mut s = stream::repeat(9).take(3); + + while let Some(v) = s.next().await { + assert_eq!(v, 9); + } + # + # }) } + ``` + "#] + fn take(self, n: usize) -> Take + where + Self: Sized, + { + Take { + stream: self, + remaining: n, } } - impl Stream for std::collections::VecDeque { - type Item = T; + #[doc = r#" + Creates a stream that yields each `step`th element. - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + # Panics + + This method will panic if the given step is `0`. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use std::collections::VecDeque; + + let s: VecDeque<_> = vec![0u8, 1, 2, 3, 4].into_iter().collect(); + let mut stepped = s.step_by(2); + + assert_eq!(stepped.next().await, Some(0)); + assert_eq!(stepped.next().await, Some(2)); + assert_eq!(stepped.next().await, Some(4)); + assert_eq!(stepped.next().await, None); + + # + # }) } + ``` + "#] + fn step_by(self, step: usize) -> StepBy + where + Self: Sized, + { + StepBy::new(self, step) + } + + #[doc = r#" + Takes two streams and creates a new stream over both in sequence. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use std::collections::VecDeque; + + let first: VecDeque<_> = vec![0u8, 1].into_iter().collect(); + let second: VecDeque<_> = vec![2, 3].into_iter().collect(); + let mut c = first.chain(second); + + assert_eq!(c.next().await, Some(0)); + assert_eq!(c.next().await, Some(1)); + assert_eq!(c.next().await, Some(2)); + assert_eq!(c.next().await, Some(3)); + assert_eq!(c.next().await, None); + + # + # }) } + ``` + "#] + fn chain(self, other: U) -> Chain + where + Self: Sized, + U: Stream + Sized, + { + Chain::new(self, other) + } + + #[doc = r#" + Creates a stream that gives the current element's count as well as the next value. + + # Overflow behaviour. + + This combinator does no guarding against overflows. + + # Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use std::collections::VecDeque; + + let s: VecDeque<_> = vec!['a', 'b', 'c'].into_iter().collect(); + let mut s = s.enumerate(); + + assert_eq!(s.next().await, Some((0, 'a'))); + assert_eq!(s.next().await, Some((1, 'b'))); + assert_eq!(s.next().await, Some((2, 'c'))); + assert_eq!(s.next().await, None); + + # + # }) } + ``` + "#] + fn enumerate(self) -> Enumerate + where + Self: Sized, + { + Enumerate::new(self) + } + + #[doc = r#" + A combinator that does something with each element in the stream, passing the value + on. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use std::collections::VecDeque; + + let a: VecDeque<_> = vec![1u8, 2, 3, 4, 5].into_iter().collect(); + let sum = a + .inspect(|x| println!("about to filter {}", x)) + .filter(|x| x % 2 == 0) + .inspect(|x| println!("made it through filter: {}", x)) + .fold(0, |sum, i| sum + i).await; + + assert_eq!(sum, 6); + # + # }) } + ``` + "#] + fn inspect(self, f: F) -> Inspect + where + Self: Sized, + F: FnMut(&Self::Item), + { + Inspect::new(self, f) + } + + #[doc = r#" + Transforms this `Stream` into a "fused" `Stream` such that after the first time + `poll` returns `Poll::Ready(None)`, all future calls to `poll` will also return + `Poll::Ready(None)`. + + # Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use async_std::stream; + + let mut s = stream::once(1).fuse(); + assert_eq!(s.next().await, Some(1)); + assert_eq!(s.next().await, None); + assert_eq!(s.next().await, None); + # + # }) } + ``` + "#] + fn fuse(self) -> Fuse + where + Self: Sized, + { + Fuse { + stream: self, + done: false, } } - impl Stream for std::panic::AssertUnwindSafe { - type Item = S::Item; + #[doc = r#" + Creates a stream that uses a predicate to determine if an element should be yielded. - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let s: VecDeque = vec![1, 2, 3, 4].into_iter().collect(); + let mut s = s.filter(|i| i % 2 == 0); + + assert_eq!(s.next().await, Some(2)); + assert_eq!(s.next().await, Some(4)); + assert_eq!(s.next().await, None); + # + # }) } + ``` + "#] + fn filter

(self, predicate: P) -> Filter + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + Filter::new(self, predicate) + } + + #[doc = r#" + Both filters and maps a stream. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let s: VecDeque<&str> = vec!["1", "lol", "3", "NaN", "5"].into_iter().collect(); + + let mut parsed = s.filter_map(|a| a.parse::().ok()); + + let one = parsed.next().await; + assert_eq!(one, Some(1)); + + let three = parsed.next().await; + assert_eq!(three, Some(3)); + + let five = parsed.next().await; + assert_eq!(five, Some(5)); + + let end = parsed.next().await; + assert_eq!(end, None); + # + # }) } + ``` + "#] + fn filter_map(self, f: F) -> FilterMap + where + Self: Sized, + F: FnMut(Self::Item) -> Option, + { + FilterMap::new(self, f) + } + + #[doc = r#" + Returns the element that gives the minimum value with respect to the + specified comparison function. If several elements are equally minimum, + the first element is returned. If the stream is empty, `None` is returned. + + # Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let s: VecDeque = vec![1, 2, 3].into_iter().collect(); + + let min = Stream::min_by(s.clone(), |x, y| x.cmp(y)).await; + assert_eq!(min, Some(1)); + + let min = Stream::min_by(s, |x, y| y.cmp(x)).await; + assert_eq!(min, Some(3)); + + let min = Stream::min_by(VecDeque::::new(), |x, y| x.cmp(y)).await; + assert_eq!(min, None); + # + # }) } + ``` + "#] + fn min_by(self, compare: F) -> impl Future> [MinByFuture] + where + Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + MinByFuture::new(self, compare) + } + + #[doc = r#" + Returns the nth element of the stream. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); + + let second = s.nth(1).await; + assert_eq!(second, Some(2)); + # + # }) } + ``` + Calling `nth()` multiple times: + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); + + let second = s.nth(0).await; + assert_eq!(second, Some(1)); + + let second = s.nth(0).await; + assert_eq!(second, Some(2)); + # + # }) } + ``` + Returning `None` if the stream finished before returning `n` elements: + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); + + let fourth = s.nth(4).await; + assert_eq!(fourth, None); + # + # }) } + ``` + "#] + fn nth(&mut self, n: usize) -> impl Future> + '_ [NthFuture<'_, Self>] + where + Self: Sized, + { + NthFuture::new(self, n) + } + + #[doc = r#" + Tests if every element of the stream matches a predicate. + + `all()` takes a closure that returns `true` or `false`. It applies + this closure to each element of the stream, and if they all return + `true`, then so does `all()`. If any of them return `false`, it + returns `false`. + + `all()` is short-circuiting; in other words, it will stop processing + as soon as it finds a `false`, given that no matter what else happens, + the result will also be `false`. + + An empty stream returns `true`. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use async_std::stream; + + let mut s = stream::repeat::(42).take(3); + assert!(s.all(|x| x == 42).await); + + # + # }) } + ``` + + Empty stream: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use async_std::stream; + + let mut s = stream::empty::(); + assert!(s.all(|_| false).await); + # + # }) } + ``` + "#] + #[inline] + fn all(&mut self, f: F) -> impl Future + '_ [AllFuture<'_, Self, F, Self::Item>] + where + Self: Unpin + Sized, + F: FnMut(Self::Item) -> bool, + { + AllFuture { + stream: self, + result: true, // the default if the empty stream + _marker: PhantomData, + f, } } - } else { - pub use futures_core::stream::Stream; + + #[doc = r#" + Searches for an element in a stream that satisfies a predicate. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use std::collections::VecDeque; + + let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); + let res = s.find(|x| *x == 2).await; + assert_eq!(res, Some(2)); + # + # }) } + ``` + + Resuming after a first find: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use std::collections::VecDeque; + + let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); + let res = s.find(|x| *x == 2).await; + assert_eq!(res, Some(2)); + + let next = s.next().await; + assert_eq!(next, Some(3)); + # + # }) } + ``` + "#] + fn find

(&mut self, p: P) -> impl Future> + '_ [FindFuture<'_, Self, P, Self::Item>] + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + FindFuture::new(self, p) + } + + #[doc = r#" + Applies function to the elements of stream and returns the first non-none result. + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use std::collections::VecDeque; + + let mut s: VecDeque<&str> = vec!["lol", "NaN", "2", "5"].into_iter().collect(); + let first_number = s.find_map(|s| s.parse().ok()).await; + + assert_eq!(first_number, Some(2)); + # + # }) } + ``` + "#] + fn find_map(&mut self, f: F) -> impl Future> + '_ [FindMapFuture<'_, Self, F, Self::Item, B>] + where + Self: Sized, + F: FnMut(Self::Item) -> Option, + { + FindMapFuture::new(self, f) + } + + #[doc = r#" + A combinator that applies a function to every element in a stream + producing a single, final value. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use std::collections::VecDeque; + + let s: VecDeque = vec![1, 2, 3].into_iter().collect(); + let sum = s.fold(0, |acc, x| acc + x).await; + + assert_eq!(sum, 6); + # + # }) } + ``` + "#] + fn fold(self, init: B, f: F) -> impl Future [FoldFuture] + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + FoldFuture::new(self, init, f) + } + + #[doc = r#" + Tests if any element of the stream matches a predicate. + + `any()` takes a closure that returns `true` or `false`. It applies + this closure to each element of the stream, and if any of them return + `true`, then so does `any()`. If they all return `false`, it + returns `false`. + + `any()` is short-circuiting; in other words, it will stop processing + as soon as it finds a `true`, given that no matter what else happens, + the result will also be `true`. + + An empty stream returns `false`. + + # Examples + + Basic usage: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use async_std::stream; + + let mut s = stream::repeat::(42).take(3); + assert!(s.any(|x| x == 42).await); + # + # }) } + ``` + + Empty stream: + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use async_std::stream; + + let mut s = stream::empty::(); + assert!(!s.any(|_| false).await); + # + # }) } + ``` + "#] + #[inline] + fn any(&mut self, f: F) -> impl Future + '_ [AnyFuture<'_, Self, F, Self::Item>] + where + Self: Unpin + Sized, + F: FnMut(Self::Item) -> bool, + { + AnyFuture { + stream: self, + result: false, // the default if the empty stream + _marker: PhantomData, + f, + } + } + + #[doc = r#" + A stream adaptor similar to [`fold`] that holds internal state and produces a new + stream. + + [`fold`]: #method.fold + + `scan()` takes two arguments: an initial value which seeds the internal state, and + a closure with two arguments, the first being a mutable reference to the internal + state and the second a stream element. The closure can assign to the internal state + to share state between iterations. + + On iteration, the closure will be applied to each element of the stream and the + return value from the closure, an `Option`, is yielded by the stream. + + ## Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let s: VecDeque = vec![1, 2, 3].into_iter().collect(); + let mut s = s.scan(1, |state, x| { + *state = *state * x; + Some(-*state) + }); + + assert_eq!(s.next().await, Some(-1)); + assert_eq!(s.next().await, Some(-2)); + assert_eq!(s.next().await, Some(-6)); + assert_eq!(s.next().await, None); + # + # }) } + ``` + "#] + #[inline] + fn scan(self, initial_state: St, f: F) -> Scan + where + Self: Sized, + F: FnMut(&mut St, Self::Item) -> Option, + { + Scan::new(self, initial_state, f) + } + + #[doc = r#" + Combinator that `skip`s elements based on a predicate. + + Takes a closure argument. It will call this closure on every element in + the stream and ignore elements until it returns `false`. + + After `false` is returned, `SkipWhile`'s job is over and all further + elements in the strem are yielded. + + ## Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let a: VecDeque<_> = vec![-1i32, 0, 1].into_iter().collect(); + let mut s = a.skip_while(|x| x.is_negative()); + + assert_eq!(s.next().await, Some(0)); + assert_eq!(s.next().await, Some(1)); + assert_eq!(s.next().await, None); + # + # }) } + ``` + "#] + fn skip_while

(self, predicate: P) -> SkipWhile + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + SkipWhile::new(self, predicate) + } + + #[doc = r#" + Creates a combinator that skips the first `n` elements. + + ## Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + let s: VecDeque = vec![1, 2, 3].into_iter().collect(); + let mut skipped = s.skip(2); + + assert_eq!(skipped.next().await, Some(3)); + assert_eq!(skipped.next().await, None); + # + # }) } + ``` + "#] + fn skip(self, n: usize) -> Skip + where + Self: Sized, + { + Skip::new(self, n) + } + + #[doc = r#" + 'Zips up' two streams into a single stream of pairs. + + `zip()` returns a new stream that will iterate over two other streams, returning a + tuple where the first element comes from the first stream, and the second element + comes from the second stream. + + In other words, it zips two streams together, into a single one. + + If either stream returns [`None`], [`poll_next`] from the zipped stream will return + [`None`]. If the first stream returns [`None`], `zip` will short-circuit and + `poll_next` will not be called on the second stream. + + [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None + [`poll_next`]: #tymethod.poll_next + + ## Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use std::collections::VecDeque; + use async_std::stream::Stream; + + let l: VecDeque = vec![1, 2, 3].into_iter().collect(); + let r: VecDeque = vec![4, 5, 6, 7].into_iter().collect(); + let mut s = l.zip(r); + + assert_eq!(s.next().await, Some((1, 4))); + assert_eq!(s.next().await, Some((2, 5))); + assert_eq!(s.next().await, Some((3, 6))); + assert_eq!(s.next().await, None); + # + # }) } + ``` + "#] + #[inline] + fn zip(self, other: U) -> Zip + where + Self: Sized + Stream, + U: Stream, + { + Zip::new(self, other) + } + + #[doc = r#" + Transforms a stream into a collection. + + `collect()` can take anything streamable, and turn it into a relevant + collection. This is one of the more powerful methods in the async + standard library, used in a variety of contexts. + + The most basic pattern in which `collect()` is used is to turn one + collection into another. You take a collection, call [`stream`] on it, + do a bunch of transformations, and then `collect()` at the end. + + Because `collect()` is so general, it can cause problems with type + inference. As such, `collect()` is one of the few times you'll see + the syntax affectionately known as the 'turbofish': `::<>`. This + helps the inference algorithm understand specifically which collection + you're trying to collect into. + + # Examples + + ``` + # fn main() { async_std::task::block_on(async { + # + use async_std::prelude::*; + use async_std::stream; + + let s = stream::repeat(9u8).take(3); + let buf: Vec = s.collect().await; + + assert_eq!(buf, vec![9; 3]); + + // You can also collect streams of Result values + // into any collection that implements FromStream + let s = stream::repeat(Ok(9)).take(3); + // We are using Vec here, but other collections + // are supported as well + let buf: Result, ()> = s.collect().await; + + assert_eq!(buf, Ok(vec![9; 3])); + + // The stream will stop on the first Err and + // return that instead + let s = stream::repeat(Err(5)).take(3); + let buf: Result, u8> = s.collect().await; + + assert_eq!(buf, Err(5)); + # + # }) } + ``` + + [`stream`]: trait.Stream.html#tymethod.next + "#] + #[cfg(any(feature = "unstable", feature = "docs"))] + #[cfg_attr(feature = "docs", doc(cfg(unstable)))] + #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead (TODO)"] + fn collect<'a, B>(self) -> impl Future + 'a [Pin + 'a>>] + where + Self: Sized + 'a, + B: FromStream, + { + FromStream::from_stream(self) + } + } + + impl Stream for Box { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + } + + impl Stream for &mut S { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + } + + impl

Stream for Pin

+ where + P: DerefMut + Unpin, +

::Target: Stream, + { + type Item = <

::Target as Stream>::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + } + + impl Stream for std::collections::VecDeque { + type Item = T; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } + } + + impl Stream for std::panic::AssertUnwindSafe { + type Item = S::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unreachable!() + } } } - -#[doc(hidden)] -pub trait StreamExt: futures_core::stream::Stream { - fn next(&mut self) -> NextFuture<'_, Self> - where - Self: Unpin, - { - NextFuture { stream: self } - } - - fn take(self, n: usize) -> Take - where - Self: Sized, - { - Take { - stream: self, - remaining: n, - } - } - - fn step_by(self, step: usize) -> StepBy - where - Self: Sized, - { - StepBy::new(self, step) - } - - fn chain(self, other: U) -> Chain - where - Self: Sized, - U: Stream + Sized, - { - Chain::new(self, other) - } - - fn enumerate(self) -> Enumerate - where - Self: Sized, - { - Enumerate::new(self) - } - - fn inspect(self, f: F) -> Inspect - where - Self: Sized, - F: FnMut(&Self::Item), - { - Inspect::new(self, f) - } - - fn fuse(self) -> Fuse - where - Self: Sized, - { - Fuse { - stream: self, - done: false, - } - } - - fn filter

(self, predicate: P) -> Filter - where - Self: Sized, - P: FnMut(&Self::Item) -> bool, - { - Filter::new(self, predicate) - } - - fn filter_map(self, f: F) -> FilterMap - where - Self: Sized, - F: FnMut(Self::Item) -> Option, - { - FilterMap::new(self, f) - } - - fn min_by(self, compare: F) -> MinByFuture - where - Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Ordering, - { - MinByFuture::new(self, compare) - } - - fn nth(&mut self, n: usize) -> NthFuture<'_, Self> - where - Self: Sized, - { - NthFuture::new(self, n) - } - - #[inline] - fn all(&mut self, f: F) -> AllFuture<'_, Self, F, Self::Item> - where - Self: Unpin + Sized, - F: FnMut(Self::Item) -> bool, - { - AllFuture { - stream: self, - result: true, // the default if the empty stream - _marker: PhantomData, - f, - } - } - - fn find

(&mut self, p: P) -> FindFuture<'_, Self, P, Self::Item> - where - Self: Sized, - P: FnMut(&Self::Item) -> bool, - { - FindFuture::new(self, p) - } - - fn find_map(&mut self, f: F) -> FindMapFuture<'_, Self, F, Self::Item, B> - where - Self: Sized, - F: FnMut(Self::Item) -> Option, - { - FindMapFuture::new(self, f) - } - - fn fold(self, init: B, f: F) -> FoldFuture - where - Self: Sized, - F: FnMut(B, Self::Item) -> B, - { - FoldFuture::new(self, init, f) - } - - fn any(&mut self, f: F) -> AnyFuture<'_, Self, F, Self::Item> - where - Self: Unpin + Sized, - F: FnMut(Self::Item) -> bool, - { - AnyFuture { - stream: self, - result: false, // the default if the empty stream - _marker: PhantomData, - f, - } - } - - fn scan(self, initial_state: St, f: F) -> Scan - where - Self: Sized, - F: FnMut(&mut St, Self::Item) -> Option, - { - Scan::new(self, initial_state, f) - } - - fn skip_while

(self, predicate: P) -> SkipWhile - where - Self: Sized, - P: FnMut(&Self::Item) -> bool, - { - SkipWhile::new(self, predicate) - } - - fn skip(self, n: usize) -> Skip - where - Self: Sized, - { - Skip::new(self, n) - } - - fn zip(self, other: U) -> Zip - where - Self: Stream + Sized, - U: Stream, - { - Zip::new(self, other) - } - - #[cfg(any(feature = "unstable", feature = "docs"))] - #[cfg_attr(feature = "docs", doc(cfg(unstable)))] - #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead (TODO)"] - fn collect<'a, B>(self) -> Pin + 'a>> - where - Self: Sized + 'a, - B: FromStream, - { - FromStream::from_stream(self) - } -} - -impl StreamExt for T {} diff --git a/src/utils.rs b/src/utils.rs index 258042d..289c83e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -19,3 +19,89 @@ pub fn abort_on_panic(f: impl FnOnce() -> T) -> T { mem::forget(bomb); 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(std::marker::PhantomData); + } + + #[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 $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 [$f:ty] $($tail:tt)*) => { + extension_trait!(@doc ($($head)* -> owned::ImplFuture<$out>) $($tail)*); + }; + (@ext ($($head:tt)*) -> impl Future [$f:ty] $($tail:tt)*) => { + extension_trait!(@ext ($($head)* -> $f) $($tail)*); + }; + + (@doc ($($head:tt)*) -> impl Future + $lt:lifetime [$f:ty] $($tail:tt)*) => { + extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$lt, $out>) $($tail)*); + }; + (@ext ($($head:tt)*) -> impl Future + $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; From ff028bb540f85c3399796ae1e692df6cc0c2cf44 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 26 Sep 2019 14:21:27 -0400 Subject: [PATCH 2/4] Improve compile times and add comments --- src/io/buf_read/mod.rs | 314 ++++++++++++++++++++------------------ src/io/read/mod.rs | 322 +++++++++++++++++++++------------------ src/io/seek.rs | 92 +++++------ src/io/write/mod.rs | 255 +++++++++++++++++-------------- src/os/unix/net/mod.rs | 6 +- src/stream/stream/mod.rs | 90 +++++++---- src/utils.rs | 79 +++++++--- 7 files changed, 640 insertions(+), 518 deletions(-) diff --git a/src/io/buf_read/mod.rs b/src/io/buf_read/mod.rs index ad8df85..d34b2ae 100644 --- a/src/io/buf_read/mod.rs +++ b/src/io/buf_read/mod.rs @@ -22,91 +22,99 @@ cfg_if! { } extension_trait! { - /// 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 + #[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 [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. + #[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>; - /// Tells this buffer that `amt` bytes have been consumed from the buffer, so they - /// should no longer be returned in calls to `read`. + #[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); - /// 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(()) }) } - /// ``` + #[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, @@ -123,42 +131,44 @@ extension_trait! { } } - /// 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(()) }) } - /// ``` + #[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, @@ -174,35 +184,37 @@ extension_trait! { } } - /// 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(()) }) } - /// ``` + #[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, @@ -221,11 +233,11 @@ extension_trait! { self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn consume(self: Pin<&mut Self>, amt: usize) { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -234,11 +246,11 @@ extension_trait! { self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn consume(self: Pin<&mut Self>, amt: usize) { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -251,11 +263,11 @@ extension_trait! { self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn consume(self: Pin<&mut Self>, amt: usize) { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -268,7 +280,7 @@ extension_trait! { } fn consume(self: Pin<&mut Self>, amt: usize) { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } } diff --git a/src/io/read/mod.rs b/src/io/read/mod.rs index 3acfc28..3827681 100644 --- a/src/io/read/mod.rs +++ b/src/io/read/mod.rs @@ -27,87 +27,100 @@ cfg_if! { } extension_trait! { - /// 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 + #[doc = r#" + 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`. + #[doc = r#" + Attempt to read from the `AsyncRead` into `buf`. + "#] fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll>; - /// Attempt to read from the `AsyncRead` into `bufs` using vectored IO operations. + #[doc = r#" + 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> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } - /// 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]) -> impl Future> + 'a [ReadFuture<'a, Self>] + #[doc = r#" + 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], + ) -> impl Future> + 'a [ReadFuture<'a, Self>] where Self: Unpin { ReadFuture { reader: self, buf } } - /// 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 + #[doc = r#" + 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>], @@ -118,31 +131,33 @@ extension_trait! { 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(()) }) } - /// ``` + #[doc = r#" + 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, @@ -158,28 +173,30 @@ extension_trait! { } } - /// 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(()) }) } - /// ``` + #[doc = r#" + 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, @@ -196,44 +213,49 @@ extension_trait! { } } - /// 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]) -> impl Future> + 'a [ReadExactFuture<'a, Self>] + #[doc = r#" + 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], + ) -> impl Future> + 'a [ReadExactFuture<'a, Self>] where Self: Unpin, { @@ -247,7 +269,7 @@ extension_trait! { cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -257,7 +279,7 @@ extension_trait! { cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -271,7 +293,7 @@ extension_trait! { cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -281,7 +303,7 @@ extension_trait! { cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } } diff --git a/src/io/seek.rs b/src/io/seek.rs index a9234f9..274eee7 100644 --- a/src/io/seek.rs +++ b/src/io/seek.rs @@ -14,53 +14,59 @@ cfg_if! { } extension_trait! { - /// 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 + #[doc = r#" + 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. + #[doc = r#" + Attempt to seek to an offset, in bytes, in a stream. + "#] fn poll_seek( self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll>; - /// 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(()) }) } - /// ``` + #[doc = r#" + 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, @@ -78,7 +84,7 @@ extension_trait! { cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -88,7 +94,7 @@ extension_trait! { cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -102,7 +108,7 @@ extension_trait! { cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } } diff --git a/src/io/write/mod.rs b/src/io/write/mod.rs index 27e7920..5e1ecc8 100644 --- a/src/io/write/mod.rs +++ b/src/io/write/mod.rs @@ -24,99 +24,115 @@ cfg_if! { } extension_trait! { - /// 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 + #[doc = r#" + 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. + #[doc = r#" + Attempt to write bytes from `buf` into the object. + "#] fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll>; - /// Attempt to write bytes from `bufs` into the object using vectored - /// IO operations. + #[doc = r#" + 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> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } - /// Attempt to flush the object, ensuring that any buffered data reach - /// their destination. + #[doc = r#" + Attempt to flush the object, ensuring that any buffered data reach + their destination. + "#] fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; - /// Attempt to close the object. + #[doc = r#" + Attempt to close the object. + "#] fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; - /// 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]) -> impl Future> + 'a [WriteFuture<'a, Self>] + #[doc = r#" + 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], + ) -> impl Future> + '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(()) }) } - /// ``` + #[doc = r#" + 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> + '_ [FlushFuture<'_, Self>] where Self: Unpin, @@ -124,16 +140,18 @@ extension_trait! { 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 + #[doc = r#" + 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>], @@ -144,31 +162,36 @@ extension_trait! { 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(()) }) } - /// ``` - /// - /// [`write`]: #tymethod.write - fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + 'a [WriteAllFuture<'a, Self>] + #[doc = r#" + 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], + ) -> impl Future> + 'a [WriteAllFuture<'a, Self>] where Self: Unpin, { @@ -182,15 +205,15 @@ extension_trait! { cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -200,15 +223,15 @@ extension_trait! { cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -222,15 +245,15 @@ extension_trait! { cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -240,15 +263,15 @@ extension_trait! { cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } } diff --git a/src/os/unix/net/mod.rs b/src/os/unix/net/mod.rs index 465db54..a719a48 100644 --- a/src/os/unix/net/mod.rs +++ b/src/os/unix/net/mod.rs @@ -55,7 +55,7 @@ cfg_if! { /// assert_eq!(addr.is_unnamed(), true); /// ``` pub fn is_unnamed(&self) -> bool { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } /// Returns the contents of this address if it is a `pathname` address. @@ -84,13 +84,13 @@ cfg_if! { /// assert_eq!(addr.as_pathname(), None); /// ``` pub fn as_pathname(&self) -> Option<&Path> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } } else { diff --git a/src/stream/stream/mod.rs b/src/stream/stream/mod.rs index ba23718..c8731bc 100644 --- a/src/stream/stream/mod.rs +++ b/src/stream/stream/mod.rs @@ -89,25 +89,29 @@ cfg_if! { } extension_trait! { - /// An asynchronous stream of values. - /// - /// This trait is a re-export of [`futures::stream::Stream`] and is an async version of - /// [`std::iter::Iterator`]. - /// - /// 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::iter::Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html - /// [`futures::stream::Stream`]: - /// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/stream/trait.Stream.html - /// [provided methods]: #provided-methods + #[doc = r#" + An asynchronous stream of values. + + This trait is a re-export of [`futures::stream::Stream`] and is an async version of + [`std::iter::Iterator`]. + + 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::iter::Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html + [`futures::stream::Stream`]: + https://docs.rs/futures-preview/0.3.0-alpha.17/futures/stream/trait.Stream.html + [provided methods]: #provided-methods + "#] pub trait Stream [StreamExt: futures_core::stream::Stream] { - /// The type of items yielded by this stream. + #[doc = r#" + The type of items yielded by this stream. + "#] type Item; #[doc = r#" @@ -493,7 +497,10 @@ extension_trait! { # }) } ``` "#] - fn min_by(self, compare: F) -> impl Future> [MinByFuture] + fn min_by( + self, + compare: F, + )-> impl Future> [MinByFuture] where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, @@ -554,7 +561,10 @@ extension_trait! { # }) } ``` "#] - fn nth(&mut self, n: usize) -> impl Future> + '_ [NthFuture<'_, Self>] + fn nth( + &mut self, + n: usize, + ) -> impl Future> + '_ [NthFuture<'_, Self>] where Self: Sized, { @@ -607,7 +617,10 @@ extension_trait! { ``` "#] #[inline] - fn all(&mut self, f: F) -> impl Future + '_ [AllFuture<'_, Self, F, Self::Item>] + fn all( + &mut self, + f: F, + ) -> impl Future + '_ [AllFuture<'_, Self, F, Self::Item>] where Self: Unpin + Sized, F: FnMut(Self::Item) -> bool, @@ -658,7 +671,10 @@ extension_trait! { # }) } ``` "#] - fn find

(&mut self, p: P) -> impl Future> + '_ [FindFuture<'_, Self, P, Self::Item>] + fn find

( + &mut self, + p: P, + ) -> impl Future> + '_ [FindFuture<'_, Self, P, Self::Item>] where Self: Sized, P: FnMut(&Self::Item) -> bool, @@ -683,7 +699,10 @@ extension_trait! { # }) } ``` "#] - fn find_map(&mut self, f: F) -> impl Future> + '_ [FindMapFuture<'_, Self, F, Self::Item, B>] + fn find_map( + &mut self, + f: F, + ) -> impl Future> + '_ [FindMapFuture<'_, Self, F, Self::Item, B>] where Self: Sized, F: FnMut(Self::Item) -> Option, @@ -713,7 +732,11 @@ extension_trait! { # }) } ``` "#] - fn fold(self, init: B, f: F) -> impl Future [FoldFuture] + fn fold( + self, + init: B, + f: F, + ) -> impl Future [FoldFuture] where Self: Sized, F: FnMut(B, Self::Item) -> B, @@ -766,7 +789,10 @@ extension_trait! { ``` "#] #[inline] - fn any(&mut self, f: F) -> impl Future + '_ [AnyFuture<'_, Self, F, Self::Item>] + fn any( + &mut self, + f: F, + ) -> impl Future + '_ [AnyFuture<'_, Self, F, Self::Item>] where Self: Unpin + Sized, F: FnMut(Self::Item) -> bool, @@ -984,7 +1010,9 @@ extension_trait! { #[cfg(any(feature = "unstable", feature = "docs"))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead (TODO)"] - fn collect<'a, B>(self) -> impl Future + 'a [Pin + 'a>>] + fn collect<'a, B>( + self, + ) -> impl Future + 'a [Pin + 'a>>] where Self: Sized + 'a, B: FromStream, @@ -997,7 +1025,7 @@ extension_trait! { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -1005,7 +1033,7 @@ extension_trait! { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -1017,7 +1045,7 @@ extension_trait! { type Item = <

::Target as Stream>::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -1025,7 +1053,7 @@ extension_trait! { type Item = T; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } @@ -1033,7 +1061,7 @@ extension_trait! { type Item = S::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - unreachable!() + unreachable!("this impl only appears in the rendered docs") } } } diff --git a/src/utils.rs b/src/utils.rs index 289c83e..bdf0f3b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,56 +20,69 @@ pub fn abort_on_panic(f: impl FnOnce() -> T) -> T { t } +/// Defines an extension trait for a base trait from the `futures` crate. +/// +/// In generated docs, the base trait will contain methods from the extension trait. In actual +/// code, the base trait will be re-exported and the extension trait will be hidden. We then +/// re-export the extension trait from the prelude. +/// +/// Inside invocations of this macro, we write a definitions that looks similar to the final +/// rendered docs, and the macro then generates all the boilerplate for us. #[doc(hidden)] #[macro_export] macro_rules! extension_trait { - (@gen ($($head:tt)*) pub trait $name:ident [$ext:ident: $orig:path] { $($body:tt)* } $($imp:item)*) => { + ( + // Interesting patterns: + // - `$name`: trait name that gets rendered in the docs + // - `$ext`: name of the hidden extension trait + // - `$base`: base trait from the `futures` crate + $(#[$attr:meta])* + pub trait $name:ident [$ext:ident: $base:path] { + $($body:tt)* + } + + // Shim trait impls that only appear in docs. + $($imp:item)* + ) => { + // A fake `impl Future` type that doesn't borrow. #[allow(dead_code)] mod owned { #[doc(hidden)] pub struct ImplFuture(std::marker::PhantomData); } + // A fake `impl Future` type that borrows its environment. #[allow(dead_code)] mod borrowed { #[doc(hidden)] pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); } + // Render a fake trait containing all methods from the base trait and the extension trait. #[cfg(feature = "docs")] - $($head)* pub trait $name { + $(#[$attr])* + pub trait $name { extension_trait!(@doc () $($body)*); } + // When not rendering docs, re-export the base trait from the futures crate. #[cfg(not(feature = "docs"))] - pub use $orig as $name; + pub use $base as $name; - $($head)* pub trait $ext: $orig { + // The extension trait that adds methods to any type implementing the base trait. + $(#[$attr])* + pub trait $ext: $base { extension_trait!(@ext () $($body)*); } - impl $ext for T {} + // Blanket implementation of the extension trait for any type implementing the base trait. + impl $ext for T {} + // Shim trait impls that only appear in docs. $(#[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)*); - }; + // Parse an associated type. (@doc ($($head:tt)*) type $name:ident; $($tail:tt)*) => { extension_trait!(@doc ($($head)* type $name;) $($tail)*); }; @@ -77,6 +90,23 @@ macro_rules! extension_trait { extension_trait!(@ext ($($head)*) $($tail)*); }; + // Parse a required method. + (@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)*); + }; + + // Parse a provided method that exists in the base trait. + (@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)*); + }; + + // Parse the return type in an extension method where the future doesn't borrow. (@doc ($($head:tt)*) -> impl Future [$f:ty] $($tail:tt)*) => { extension_trait!(@doc ($($head)* -> owned::ImplFuture<$out>) $($tail)*); }; @@ -84,6 +114,7 @@ macro_rules! extension_trait { extension_trait!(@ext ($($head)* -> $f) $($tail)*); }; + // Parse the return type in an extension method where the future borrows its environment. (@doc ($($head:tt)*) -> impl Future + $lt:lifetime [$f:ty] $($tail:tt)*) => { extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$lt, $out>) $($tail)*); }; @@ -91,6 +122,7 @@ macro_rules! extension_trait { extension_trait!(@ext ($($head)* -> $f) $($tail)*); }; + // Parse a token that doesn't fit into any of the previous patterns. (@doc ($($head:tt)*) $token:tt $($tail:tt)*) => { extension_trait!(@doc ($($head)* $token) $($tail)*); }; @@ -98,10 +130,9 @@ macro_rules! extension_trait { extension_trait!(@ext ($($head)* $token) $($tail)*); }; + // Handle the end of the token list. (@doc ($($head:tt)*)) => { $($head)* }; (@ext ($($head:tt)*)) => { $($head)* }; - - ($($head:tt)*) => { extension_trait!(@gen () $($head)*); }; } pub use crate::extension_trait; From 8e32fd09f3bfd5985a027465147a2cb4f8a22200 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 26 Sep 2019 14:31:02 -0400 Subject: [PATCH 3/4] Fix a doc test --- src/stream/stream/mod.rs | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/stream/stream/mod.rs b/src/stream/stream/mod.rs index c8731bc..c182184 100644 --- a/src/stream/stream/mod.rs +++ b/src/stream/stream/mod.rs @@ -410,7 +410,8 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let s: VecDeque = vec![1, 2, 3, 4].into_iter().collect(); let mut s = s.filter(|i| i % 2 == 0); @@ -441,7 +442,8 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let s: VecDeque<&str> = vec!["1", "lol", "3", "NaN", "5"].into_iter().collect(); @@ -481,17 +483,18 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let s: VecDeque = vec![1, 2, 3].into_iter().collect(); - let min = Stream::min_by(s.clone(), |x, y| x.cmp(y)).await; + let min = s.clone().min_by(|x, y| x.cmp(y)).await; assert_eq!(min, Some(1)); - let min = Stream::min_by(s, |x, y| y.cmp(x)).await; + let min = s.min_by(|x, y| y.cmp(x)).await; assert_eq!(min, Some(3)); - let min = Stream::min_by(VecDeque::::new(), |x, y| x.cmp(y)).await; + let min = VecDeque::::new().min_by(|x, y| x.cmp(y)).await; assert_eq!(min, None); # # }) } @@ -519,7 +522,8 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); @@ -534,7 +538,8 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); @@ -551,7 +556,8 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let mut s: VecDeque = vec![1, 2, 3].into_iter().collect(); @@ -825,7 +831,8 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let s: VecDeque = vec![1, 2, 3].into_iter().collect(); let mut s = s.scan(1, |state, x| { @@ -865,7 +872,8 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let a: VecDeque<_> = vec![-1i32, 0, 1].into_iter().collect(); let mut s = a.skip_while(|x| x.is_negative()); @@ -894,7 +902,9 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; + let s: VecDeque = vec![1, 2, 3].into_iter().collect(); let mut skipped = s.skip(2); @@ -933,7 +943,8 @@ extension_trait! { # fn main() { async_std::task::block_on(async { # use std::collections::VecDeque; - use async_std::stream::Stream; + + use async_std::prelude::*; let l: VecDeque = vec![1, 2, 3].into_iter().collect(); let r: VecDeque = vec![4, 5, 6, 7].into_iter().collect(); From 414fadd6e63cf0310c487cafbffdd493cf30ca96 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 26 Sep 2019 23:13:02 -0400 Subject: [PATCH 4/4] cargo fmt --- src/io/read/mod.rs | 2 +- src/stream/stream/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io/read/mod.rs b/src/io/read/mod.rs index 3827681..5a2276e 100644 --- a/src/io/read/mod.rs +++ b/src/io/read/mod.rs @@ -10,8 +10,8 @@ use read_to_end::{read_to_end_internal, ReadToEndFuture}; use read_to_string::ReadToStringFuture; use read_vectored::ReadVectoredFuture; -use std::mem; use cfg_if::cfg_if; +use std::mem; use crate::io::IoSliceMut; use crate::utils::extension_trait; diff --git a/src/stream/stream/mod.rs b/src/stream/stream/mod.rs index c182184..07de323 100644 --- a/src/stream/stream/mod.rs +++ b/src/stream/stream/mod.rs @@ -503,7 +503,7 @@ extension_trait! { fn min_by( self, compare: F, - )-> impl Future> [MinByFuture] + ) -> impl Future> [MinByFuture] where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,