#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "std")]
use core::any::Any;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
#[cfg(feature = "std")]
use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe};
#[doc(no_inline)]
pub use core::future::{pending, ready, Pending, Ready};
#[cfg(feature = "std")]
use pin_project_lite::pin_project;
#[doc(no_inline)]
pub use completion_core::CompletionFuture;
use super::{Adapter, MustComplete};
#[cfg(feature = "std")]
mod block_on;
#[cfg(feature = "std")]
pub use block_on::block_on;
#[cfg(feature = "std")]
mod join;
#[cfg(feature = "std")]
pub use join::{
race, race_all, race_ok, race_ok_all, try_zip, try_zip_all, zip, zip_all, Race, RaceAll,
RaceOk, RaceOkAll, RaceOkAllErrors, TryZip, TryZipAll, TryZipAllOutput, Zip, ZipAll,
ZipAllOutput,
};
mod now_or_never;
pub use now_or_never::NowOrNever;
pub trait CompletionFutureExt: CompletionFuture {
unsafe fn poll(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output>
where
Self: Unpin,
{
Pin::new(self).poll(cx)
}
unsafe fn poll_cancel(&mut self, cx: &mut Context<'_>) -> Poll<()>
where
Self: Unpin,
{
Pin::new(self).poll_cancel(cx)
}
fn must_complete(self) -> MustComplete<Self>
where
Self: Sized,
{
MustComplete { inner: self }
}
fn now_or_never(self) -> NowOrNever<Self>
where
Self: Sized,
{
NowOrNever::new(self)
}
#[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
fn catch_unwind(self) -> CatchUnwind<Self>
where
Self: Sized + UnwindSafe,
{
CatchUnwind { inner: self }
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
fn boxed<'a>(self) -> BoxCompletionFuture<'a, Self::Output>
where
Self: Sized + Send + 'a,
{
Box::pin(self)
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
fn boxed_local<'a>(self) -> LocalBoxCompletionFuture<'a, Self::Output>
where
Self: Sized + 'a,
{
Box::pin(self)
}
}
impl<T: CompletionFuture + ?Sized> CompletionFutureExt for T {}
#[cfg(feature = "std")]
pin_project! {
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
#[derive(Debug)]
#[must_use = "futures do nothing unless you use them"]
pub struct CatchUnwind<F: ?Sized> {
#[pin]
inner: F,
}
}
#[cfg(feature = "std")]
impl<F: CompletionFuture + UnwindSafe + ?Sized> CompletionFuture for CatchUnwind<F> {
type Output = Result<F::Output, Box<dyn Any + Send>>;
unsafe fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
catch_unwind(AssertUnwindSafe(|| self.project().inner.poll(cx)))?.map(Ok)
}
unsafe fn poll_cancel(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
catch_unwind(AssertUnwindSafe(|| self.project().inner.poll_cancel(cx)))
.unwrap_or(Poll::Ready(()))
}
}
#[cfg(feature = "std")]
impl<F: Future + UnwindSafe + ?Sized> Future for CatchUnwind<F> {
type Output = Result<F::Output, Box<dyn Any + Send>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
catch_unwind(AssertUnwindSafe(|| self.project().inner.poll(cx)))?.map(Ok)
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub type BoxCompletionFuture<'a, T> = Pin<Box<dyn CompletionFuture<Output = T> + Send + 'a>>;
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub type LocalBoxCompletionFuture<'a, T> = Pin<Box<dyn CompletionFuture<Output = T> + 'a>>;
pub trait FutureExt: Future + Sized {
fn into_completion(self) -> Adapter<Self> {
Adapter(self)
}
}
impl<T: Future> FutureExt for T {}