Simplify extension traits using a macro

staging
Stjepan Glavina 5 years ago
parent f922e9c034
commit 79eab9eb9a

@ -13,14 +13,15 @@ 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
@ -38,7 +39,7 @@ cfg_if! {
/// [`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 {
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.
///
@ -110,11 +111,16 @@ cfg_if! {
&'a mut self,
byte: u8,
buf: &'a mut Vec<u8>,
) -> ImplFuture<'a, io::Result<usize>>
) -> impl Future<Output = usize> + 'a [ReadUntilFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
ReadUntilFuture {
reader: self,
byte,
buf,
read: 0,
}
}
/// Reads all bytes and appends them into `buf` until a newline (the 0xA byte) is
@ -156,11 +162,16 @@ cfg_if! {
fn read_line<'a>(
&'a mut self,
buf: &'a mut String,
) -> ImplFuture<'a, io::Result<usize>>
) -> impl Future<Output = io::Result<usize>> + 'a [ReadLineFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
ReadLineFuture {
reader: self,
bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) },
buf,
read: 0,
}
}
/// Returns a stream over the lines of this byte stream.
@ -196,7 +207,12 @@ cfg_if! {
where
Self: Unpin + Sized,
{
unreachable!()
Lines {
reader: self,
buf: String::new(),
bytes: Vec::new(),
read: 0,
}
}
}
@ -255,51 +271,7 @@ cfg_if! {
unreachable!()
}
}
} 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<u8>) -> ReadUntilFuture<'a, Self>
where
Self: Unpin,
{
ReadUntilFuture {
reader: self,
byte,
buf,
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,
}
}
fn lines(self) -> Lines<Self>
where
Self: Unpin + Sized,
{
Lines {
reader: self,
buf: String::new(),
bytes: Vec::new(),
read: 0,
}
}
}
impl<T: futures_io::AsyncBufRead + ?Sized> BufReadExt for T {}
pub fn read_until_internal<R: BufReadExt + ?Sized>(
mut reader: Pin<&mut R>,

@ -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,10 +23,10 @@ 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
@ -45,7 +45,7 @@ cfg_if! {
/// 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 {
pub trait Read [ReadExt: futures_io::AsyncRead] {
/// Attempt to read from the `AsyncRead` into `buf`.
fn poll_read(
self: Pin<&mut Self>,
@ -91,11 +91,11 @@ cfg_if! {
/// #
/// # Ok(()) }) }
/// ```
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> ImplFuture<'a, io::Result<usize>>
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future<Output = io::Result<usize>> + 'a [ReadFuture<'a, Self>]
where
Self: Unpin
{
unreachable!()
ReadFuture { reader: self, buf }
}
/// Like [`read`], except that it reads into a slice of buffers.
@ -111,11 +111,11 @@ cfg_if! {
fn read_vectored<'a>(
&'a mut self,
bufs: &'a mut [IoSliceMut<'a>],
) -> ImplFuture<'a, io::Result<usize>>
) -> impl Future<Output = io::Result<usize>> + 'a [ReadVectoredFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
ReadVectoredFuture { reader: self, bufs }
}
/// Reads all bytes from the byte stream.
@ -146,11 +146,16 @@ cfg_if! {
fn read_to_end<'a>(
&'a mut self,
buf: &'a mut Vec<u8>,
) -> ImplFuture<'a, io::Result<usize>>
) -> impl Future<Output = io::Result<usize>> + 'a [ReadToEndFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
let start_len = buf.len();
ReadToEndFuture {
reader: self,
buf,
start_len,
}
}
/// Reads all bytes from the byte stream and appends them into a string.
@ -178,11 +183,17 @@ cfg_if! {
fn read_to_string<'a>(
&'a mut self,
buf: &'a mut String,
) -> ImplFuture<'a, io::Result<usize>>
) -> impl Future<Output = io::Result<usize>> + 'a [ReadToStringFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
let start_len = buf.len();
ReadToStringFuture {
reader: self,
bytes: unsafe { mem::replace(buf.as_mut_vec(), Vec::new()) },
buf,
start_len,
}
}
/// Reads the exact number of bytes required to fill `buf`.
@ -222,11 +233,11 @@ cfg_if! {
/// #
/// # Ok(()) }) }
/// ```
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ImplFuture<'a, io::Result<()>>
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future<Output = io::Result<()>> + 'a [ReadExactFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
ReadExactFuture { reader: self, buf }
}
}
@ -273,61 +284,4 @@ cfg_if! {
unreachable!()
}
}
} 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<u8>) -> ReadToEndFuture<'a, Self>
where
Self: Unpin,
{
let start_len = buf.len();
ReadToEndFuture {
reader: self,
buf,
start_len,
}
}
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,
}
}
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExactFuture<'a, Self>
where
Self: Unpin,
{
ReadExactFuture { reader: self, buf }
}
}
impl<T: futures_io::AsyncRead + ?Sized> ReadExt for T {}

@ -5,14 +5,15 @@ 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<T>(std::marker::PhantomData<T>);
extension_trait! {
/// Allows seeking through a byte stream.
///
/// This trait is a re-export of [`futures::io::AsyncSeek`] and is an async version of
@ -30,7 +31,7 @@ cfg_if! {
/// [`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 {
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>,
@ -60,11 +61,14 @@ cfg_if! {
/// #
/// # Ok(()) }) }
/// ```
fn seek(&mut self, pos: SeekFrom) -> ImplFuture<io::Result<u64>>
fn seek(
&mut self,
pos: SeekFrom,
) -> impl Future<Output = io::Result<u64>> [SeekFuture<'_, Self>]
where
Self: Unpin
Self: Unpin,
{
unreachable!()
SeekFuture { seeker: self, pos }
}
}
@ -101,23 +105,8 @@ cfg_if! {
unreachable!()
}
}
} else {
pub use futures_io::AsyncSeek as Seek;
}
}
#[doc(hidden)]
pub trait SeekExt: futures_io::AsyncSeek {
fn seek(&mut self, pos: SeekFrom) -> SeekFuture<'_, Self>
where
Self: Unpin,
{
SeekFuture { seeker: self, pos }
}
}
impl<T: futures_io::AsyncSeek + ?Sized> SeekExt for T {}
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct SeekFuture<'a, T: Unpin + ?Sized> {

@ -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,10 +20,10 @@ 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
@ -44,7 +45,7 @@ cfg_if! {
/// [`poll_write_vectored`]: #method.poll_write_vectored
/// [`poll_flush`]: #tymethod.poll_flush
/// [`poll_close`]: #tymethod.poll_close
pub trait Write {
pub trait Write [WriteExt: futures_io::AsyncWrite] {
/// Attempt to write bytes from `buf` into the object.
fn poll_write(
self: Pin<&mut Self>,
@ -92,11 +93,11 @@ cfg_if! {
/// #
/// # Ok(()) }) }
/// ```
fn write<'a>(&'a mut self, buf: &'a [u8]) -> ImplFuture<'a, io::Result<usize>>
fn write<'a>(&'a mut self, buf: &'a [u8]) -> impl Future<Output = io::Result<usize>> + 'a [WriteFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
WriteFuture { writer: self, buf }
}
/// Flushes the stream to ensure that all buffered contents reach their destination.
@ -116,11 +117,11 @@ cfg_if! {
/// #
/// # Ok(()) }) }
/// ```
fn flush(&mut self) -> ImplFuture<'_, io::Result<()>>
fn flush(&mut self) -> impl Future<Output = io::Result<()>> + '_ [FlushFuture<'_, Self>]
where
Self: Unpin,
{
unreachable!()
FlushFuture { writer: self }
}
/// Like [`write`], except that it writes from a slice of buffers.
@ -136,11 +137,11 @@ cfg_if! {
fn write_vectored<'a>(
&'a mut self,
bufs: &'a [IoSlice<'a>],
) -> ImplFuture<'a, io::Result<usize>>
) -> impl Future<Output = io::Result<usize>> + 'a [WriteVectoredFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
WriteVectoredFuture { writer: self, bufs }
}
/// Writes an entire buffer into the byte stream.
@ -167,11 +168,11 @@ cfg_if! {
/// ```
///
/// [`write`]: #tymethod.write
fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> ImplFuture<'a, io::Result<()>>
fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future<Output = io::Result<()>> + 'a [WriteAllFuture<'a, Self>]
where
Self: Unpin,
{
unreachable!()
WriteAllFuture { writer: self, buf }
}
}
@ -250,40 +251,4 @@ cfg_if! {
unreachable!()
}
}
} else {
pub use futures_io::AsyncWrite as Write;
}
}
#[doc(hidden)]
pub trait WriteExt: Write {
fn write<'a>(&'a mut self, buf: &'a [u8]) -> WriteFuture<'a, Self>
where
Self: Unpin,
{
WriteFuture { writer: self, buf }
}
fn flush(&mut self) -> FlushFuture<'_, Self>
where
Self: Unpin,
{
FlushFuture { writer: self }
}
fn write_vectored<'a>(&'a mut self, bufs: &'a [IoSlice<'a>]) -> WriteVectoredFuture<'a, Self>
where
Self: Unpin,
{
WriteVectoredFuture { writer: self, bufs }
}
fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> WriteAllFuture<'a, Self>
where
Self: Unpin,
{
WriteAllFuture { writer: self, buf }
}
}
impl<T: Write + ?Sized> WriteExt for T {}

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

File diff suppressed because it is too large Load Diff

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

Loading…
Cancel
Save