Improve compile times and add comments

staging
Stjepan Glavina 5 years ago
parent 79eab9eb9a
commit ff028bb540

@ -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<io::Result<&[u8]>>;
/// Tells this buffer that `amt` bytes have been consumed from the buffer, so they
/// should no longer be returned in calls to `read`.
#[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<Self>
where
Self: Unpin + Sized,
@ -221,11 +233,11 @@ extension_trait! {
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<io::Result<&[u8]>> {
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<io::Result<&[u8]>> {
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<io::Result<&[u8]>> {
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")
}
}
}

@ -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<io::Result<usize>>;
/// 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<io::Result<usize>> {
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<Output = io::Result<usize>> + '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<Output = io::Result<usize>> + '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<u8>,
@ -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<Output = io::Result<()>> + '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<Output = io::Result<()>> + 'a [ReadExactFuture<'a, Self>]
where
Self: Unpin,
{
@ -247,7 +269,7 @@ extension_trait! {
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -257,7 +279,7 @@ extension_trait! {
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -271,7 +293,7 @@ extension_trait! {
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -281,7 +303,7 @@ extension_trait! {
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
}

@ -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<io::Result<u64>>;
/// Seeks to a new position in a byte stream.
///
/// Returns the new position in the byte stream.
///
/// A seek beyond the end of stream is allowed, but behavior is defined by the
/// implementation.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::io::SeekFrom;
/// use async_std::prelude::*;
///
/// let mut file = File::open("a.txt").await?;
///
/// let file_len = file.seek(SeekFrom::End(0)).await?;
/// #
/// # Ok(()) }) }
/// ```
#[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<io::Result<u64>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -88,7 +94,7 @@ extension_trait! {
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -102,7 +108,7 @@ extension_trait! {
cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<io::Result<u64>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
}

@ -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<io::Result<usize>>;
/// 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<io::Result<usize>> {
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<io::Result<()>>;
/// Attempt to close the object.
#[doc = r#"
Attempt to close the object.
"#]
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
/// Writes some bytes into the byte stream.
///
/// Returns the number of bytes written from the start of the buffer.
///
/// If the return value is `Ok(n)` then it must be guaranteed that
/// `0 <= n <= buf.len()`. A return value of `0` typically means that the underlying
/// object is no longer able to accept bytes and will likely not be able to in the
/// future as well, or that the buffer provided is empty.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::create("a.txt").await?;
///
/// let n = file.write(b"hello world").await?;
/// #
/// # Ok(()) }) }
/// ```
fn write<'a>(&'a mut self, buf: &'a [u8]) -> impl Future<Output = io::Result<usize>> + '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<Output = io::Result<usize>> + 'a [WriteFuture<'a, Self>]
where
Self: Unpin,
{
WriteFuture { writer: self, buf }
}
/// Flushes the stream to ensure that all buffered contents reach their destination.
///
/// # Examples
///
/// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs::File;
/// use async_std::prelude::*;
///
/// let mut file = File::create("a.txt").await?;
///
/// file.write_all(b"hello world").await?;
/// file.flush().await?;
/// #
/// # Ok(()) }) }
/// ```
#[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<Output = io::Result<()>> + '_ [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<Output = io::Result<()>> + '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<Output = io::Result<()>> + 'a [WriteAllFuture<'a, Self>]
where
Self: Unpin,
{
@ -182,15 +205,15 @@ extension_trait! {
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -200,15 +223,15 @@ extension_trait! {
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -222,15 +245,15 @@ extension_trait! {
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -240,15 +263,15 @@ extension_trait! {
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
}

@ -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 {

@ -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<F>(self, compare: F) -> impl Future<Output = Option<Self::Item>> [MinByFuture<Self, F, Self::Item>]
fn min_by<F>(
self,
compare: F,
)-> impl Future<Output = Option<Self::Item>> [MinByFuture<Self, F, Self::Item>]
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
@ -554,7 +561,10 @@ extension_trait! {
# }) }
```
"#]
fn nth(&mut self, n: usize) -> impl Future<Output = Option<Self::Item>> + '_ [NthFuture<'_, Self>]
fn nth(
&mut self,
n: usize,
) -> impl Future<Output = Option<Self::Item>> + '_ [NthFuture<'_, Self>]
where
Self: Sized,
{
@ -607,7 +617,10 @@ extension_trait! {
```
"#]
#[inline]
fn all<F>(&mut self, f: F) -> impl Future<Output = bool> + '_ [AllFuture<'_, Self, F, Self::Item>]
fn all<F>(
&mut self,
f: F,
) -> impl Future<Output = bool> + '_ [AllFuture<'_, Self, F, Self::Item>]
where
Self: Unpin + Sized,
F: FnMut(Self::Item) -> bool,
@ -658,7 +671,10 @@ extension_trait! {
# }) }
```
"#]
fn find<P>(&mut self, p: P) -> impl Future<Output = Option<Self::Item>> + '_ [FindFuture<'_, Self, P, Self::Item>]
fn find<P>(
&mut self,
p: P,
) -> impl Future<Output = Option<Self::Item>> + '_ [FindFuture<'_, Self, P, Self::Item>]
where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
@ -683,7 +699,10 @@ extension_trait! {
# }) }
```
"#]
fn find_map<F, B>(&mut self, f: F) -> impl Future<Output = Option<B>> + '_ [FindMapFuture<'_, Self, F, Self::Item, B>]
fn find_map<F, B>(
&mut self,
f: F,
) -> impl Future<Output = Option<B>> + '_ [FindMapFuture<'_, Self, F, Self::Item, B>]
where
Self: Sized,
F: FnMut(Self::Item) -> Option<B>,
@ -713,7 +732,11 @@ extension_trait! {
# }) }
```
"#]
fn fold<B, F>(self, init: B, f: F) -> impl Future<Output = B> [FoldFuture<Self, F, Self::Item, B>]
fn fold<B, F>(
self,
init: B,
f: F,
) -> impl Future<Output = B> [FoldFuture<Self, F, Self::Item, B>]
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
@ -766,7 +789,10 @@ extension_trait! {
```
"#]
#[inline]
fn any<F>(&mut self, f: F) -> impl Future<Output = bool> + '_ [AnyFuture<'_, Self, F, Self::Item>]
fn any<F>(
&mut self,
f: F,
) -> impl Future<Output = bool> + '_ [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<Output = B> + 'a [Pin<Box<dyn Future<Output = B> + 'a>>]
fn collect<'a, B>(
self,
) -> impl Future<Output = B> + 'a [Pin<Box<dyn Future<Output = B> + 'a>>]
where
Self: Sized + 'a,
B: FromStream<Self::Item>,
@ -997,7 +1025,7 @@ extension_trait! {
type Item = S::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
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<Option<Self::Item>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
@ -1017,7 +1045,7 @@ extension_trait! {
type Item = <<P as Deref>::Target as Stream>::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
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<Option<Self::Item>> {
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<Option<Self::Item>> {
unreachable!()
unreachable!("this impl only appears in the rendered docs")
}
}
}

@ -20,42 +20,77 @@ pub fn abort_on_panic<T>(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<T>(std::marker::PhantomData<T>);
}
// 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<T: $orig + ?Sized> $ext for T {}
// Blanket implementation of the extension trait for any type implementing the base trait.
impl<T: $base + ?Sized> $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)*);
// Parse an associated type.
(@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)*);
};
// 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)*);
};
@ -63,6 +98,7 @@ macro_rules! extension_trait {
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)*);
};
@ -70,13 +106,7 @@ macro_rules! extension_trait {
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)*);
};
// Parse the return type in an extension method where the future doesn't borrow.
(@doc ($($head:tt)*) -> impl Future<Output = $out:ty> [$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<Output = $out:ty> + $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;

Loading…
Cancel
Save