//! Combinators and utilities for working with `Future`s, `Stream`s, `Sink`s, //! and the `AsyncRead` and `AsyncWrite` traits. #![cfg_attr(feature = "write-all-vectored", feature(io_slice_advance))] #![cfg_attr(not(feature = "std"), no_std)] #![warn( missing_debug_implementations, missing_docs, rust_2018_idioms, single_use_lifetimes, unreachable_pub )] #![doc(test( no_crate_inject, attr( deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code, unused_assignments, unused_variables) ) ))] #![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(all(feature = "bilock", not(feature = "unstable")))] compile_error!("The `bilock` feature requires the `unstable` feature as an explicit opt-in to unstable features"); #[cfg(feature = "alloc")] extern crate alloc; // Macro re-exports pub use futures_core::ready; pub use pin_utils::pin_mut; #[cfg(feature = "async-await")] #[macro_use] mod async_await; #[cfg(feature = "async-await")] #[doc(hidden)] pub use self::async_await::*; // Not public API. #[cfg(feature = "async-await")] #[doc(hidden)] pub mod __private { pub use crate::*; pub use core::{ option::Option::{self, None, Some}, pin::Pin, result::Result::{Err, Ok}, }; pub mod async_await { pub use crate::async_await::*; } } #[cfg(feature = "sink")] macro_rules! delegate_sink { ($field:ident, $item:ty) => { fn poll_ready( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll> { self.project().$field.poll_ready(cx) } fn start_send(self: core::pin::Pin<&mut Self>, item: $item) -> Result<(), Self::Error> { self.project().$field.start_send(item) } fn poll_flush( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll> { self.project().$field.poll_flush(cx) } fn poll_close( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll> { self.project().$field.poll_close(cx) } }; } macro_rules! delegate_future { ($field:ident) => { fn poll( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll { self.project().$field.poll(cx) } }; } macro_rules! delegate_stream { ($field:ident) => { fn poll_next( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll> { self.project().$field.poll_next(cx) } fn size_hint(&self) -> (usize, Option) { self.$field.size_hint() } }; } #[cfg(feature = "io")] #[cfg(feature = "std")] macro_rules! delegate_async_write { ($field:ident) => { fn poll_write( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, buf: &[u8], ) -> core::task::Poll> { self.project().$field.poll_write(cx, buf) } fn poll_write_vectored( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, bufs: &[std::io::IoSlice<'_>], ) -> core::task::Poll> { self.project().$field.poll_write_vectored(cx, bufs) } fn poll_flush( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll> { self.project().$field.poll_flush(cx) } fn poll_close( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll> { self.project().$field.poll_close(cx) } }; } #[cfg(feature = "io")] #[cfg(feature = "std")] macro_rules! delegate_async_read { ($field:ident) => { fn poll_read( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, buf: &mut [u8], ) -> core::task::Poll> { self.project().$field.poll_read(cx, buf) } fn poll_read_vectored( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, bufs: &mut [std::io::IoSliceMut<'_>], ) -> core::task::Poll> { self.project().$field.poll_read_vectored(cx, bufs) } }; } #[cfg(feature = "io")] #[cfg(feature = "std")] macro_rules! delegate_async_buf_read { ($field:ident) => { fn poll_fill_buf( self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll> { self.project().$field.poll_fill_buf(cx) } fn consume(self: core::pin::Pin<&mut Self>, amt: usize) { self.project().$field.consume(amt) } }; } macro_rules! delegate_access_inner { ($field:ident, $inner:ty, ($($ind:tt)*)) => { /// Acquires a reference to the underlying sink or stream that this combinator is /// pulling from. pub fn get_ref(&self) -> &$inner { (&self.$field) $($ind get_ref())* } /// Acquires a mutable reference to the underlying sink or stream that this /// combinator is pulling from. /// /// Note that care must be taken to avoid tampering with the state of the /// sink or stream which may otherwise confuse this combinator. pub fn get_mut(&mut self) -> &mut $inner { (&mut self.$field) $($ind get_mut())* } /// Acquires a pinned mutable reference to the underlying sink or stream that this /// combinator is pulling from. /// /// Note that care must be taken to avoid tampering with the state of the /// sink or stream which may otherwise confuse this combinator. pub fn get_pin_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut $inner> { self.project().$field $($ind get_pin_mut())* } /// Consumes this combinator, returning the underlying sink or stream. /// /// Note that this may discard intermediate state of this combinator, so /// care should be taken to avoid losing resources when this is called. pub fn into_inner(self) -> $inner { self.$field $($ind into_inner())* } } } macro_rules! delegate_all { (@trait Future $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { impl<$($arg),*> futures_core::future::Future for $name<$($arg),*> where $t: futures_core::future::Future $(, $($bound)*)* { type Output = <$t as futures_core::future::Future>::Output; delegate_future!(inner); } }; (@trait FusedFuture $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { impl<$($arg),*> futures_core::future::FusedFuture for $name<$($arg),*> where $t: futures_core::future::FusedFuture $(, $($bound)*)* { fn is_terminated(&self) -> bool { self.inner.is_terminated() } } }; (@trait Stream $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { impl<$($arg),*> futures_core::stream::Stream for $name<$($arg),*> where $t: futures_core::stream::Stream $(, $($bound)*)* { type Item = <$t as futures_core::stream::Stream>::Item; delegate_stream!(inner); } }; (@trait FusedStream $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { impl<$($arg),*> futures_core::stream::FusedStream for $name<$($arg),*> where $t: futures_core::stream::FusedStream $(, $($bound)*)* { fn is_terminated(&self) -> bool { self.inner.is_terminated() } } }; (@trait Sink $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { #[cfg(feature = "sink")] impl<_Item, $($arg),*> futures_sink::Sink<_Item> for $name<$($arg),*> where $t: futures_sink::Sink<_Item> $(, $($bound)*)* { type Error = <$t as futures_sink::Sink<_Item>>::Error; delegate_sink!(inner, _Item); } }; (@trait Debug $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { impl<$($arg),*> core::fmt::Debug for $name<$($arg),*> where $t: core::fmt::Debug $(, $($bound)*)* { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { core::fmt::Debug::fmt(&self.inner, f) } } }; (@trait AccessInner[$inner:ty, ($($ind:tt)*)] $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { impl<$($arg),*> $name<$($arg),*> $(where $($bound)*)* { delegate_access_inner!(inner, $inner, ($($ind)*)); } }; (@trait New[|$($param:ident: $paramt:ty),*| $cons:expr] $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => { impl<$($arg),*> $name<$($arg),*> $(where $($bound)*)* { pub(crate) fn new($($param: $paramt),*) -> Self { Self { inner: $cons } } } }; ($(#[$attr:meta])* $name:ident<$($arg:ident),*>($t:ty) : $ftrait:ident $([$($targs:tt)*])* $({$($item:tt)*})* $(where $($bound:tt)*)*) => { pin_project_lite::pin_project! { #[must_use = "futures/streams/sinks do nothing unless you `.await` or poll them"] $(#[$attr])* pub struct $name< $($arg),* > $(where $($bound)*)* { #[pin] inner: $t } } impl<$($arg),*> $name< $($arg),* > $(where $($bound)*)* { $($($item)*)* } delegate_all!(@trait $ftrait $([$($targs)*])* $name<$($arg),*>($t) $(where $($bound)*)*); }; ($(#[$attr:meta])* $name:ident<$($arg:ident),*>($t:ty) : $ftrait:ident $([$($ftargs:tt)*])* + $strait:ident $([$($stargs:tt)*])* $(+ $trait:ident $([$($targs:tt)*])*)* $({$($item:tt)*})* $(where $($bound:tt)*)*) => { delegate_all!($(#[$attr])* $name<$($arg),*>($t) : $strait $([$($stargs)*])* $(+ $trait $([$($targs)*])*)* $({$($item)*})* $(where $($bound)*)*); delegate_all!(@trait $ftrait $([$($ftargs)*])* $name<$($arg),*>($t) $(where $($bound)*)*); }; } pub mod future; #[doc(no_inline)] pub use crate::future::{Future, FutureExt, TryFuture, TryFutureExt}; pub mod stream; #[doc(no_inline)] pub use crate::stream::{Stream, StreamExt, TryStream, TryStreamExt}; #[cfg(feature = "sink")] #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] pub mod sink; #[cfg(feature = "sink")] #[doc(no_inline)] pub use crate::sink::{Sink, SinkExt}; pub mod task; pub mod never; #[cfg(feature = "compat")] #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] pub mod compat; #[cfg(feature = "io")] #[cfg_attr(docsrs, doc(cfg(feature = "io")))] #[cfg(feature = "std")] pub mod io; #[cfg(feature = "io")] #[cfg(feature = "std")] #[doc(no_inline)] pub use crate::io::{ AsyncBufRead, AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, AsyncWrite, AsyncWriteExt, }; #[cfg(feature = "alloc")] pub mod lock; #[cfg(not(futures_no_atomic_cas))] #[cfg(feature = "alloc")] mod abortable; mod fns; mod unfold_state;