use std::fmt;
#[doc(no_inline)]
pub use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use pin_project_lite::pin_project;
pub fn pending<T>() -> Pending<T> {
Pending {
_marker: PhantomData,
}
}
pub struct Pending<T> {
_marker: PhantomData<T>,
}
impl<T> Unpin for Pending<T> {}
impl<T> fmt::Debug for Pending<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Pending").finish()
}
}
impl<T> Future for Pending<T> {
type Output = T;
fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<T> {
Poll::Pending
}
}
pub fn poll_once<T, F>(f: F) -> PollOnce<F>
where
F: Future<Output = T>,
{
PollOnce { f }
}
pin_project! {
pub struct PollOnce<F> {
#[pin]
f: F,
}
}
impl<F> fmt::Debug for PollOnce<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PollOnce").finish()
}
}
impl<T, F> Future for PollOnce<F>
where
F: Future<Output = T>,
{
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
match Pin::new(&mut this.f).poll(cx) {
Poll::Ready(t) => Poll::Ready(Some(t)),
Poll::Pending => Poll::Ready(None),
}
}
}
pub fn poll_fn<T, F>(f: F) -> PollFn<F>
where
F: FnMut(&mut Context<'_>) -> Poll<T>,
{
PollFn { f }
}
pin_project! {
pub struct PollFn<F> {
f: F,
}
}
impl<F> fmt::Debug for PollFn<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PollFn").finish()
}
}
impl<T, F> Future for PollFn<F>
where
F: FnMut(&mut Context<'_>) -> Poll<T>,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
let this = self.project();
(this.f)(cx)
}
}
pub fn ready<T>(val: T) -> Ready<T> {
Ready(Some(val))
}
#[derive(Debug)]
pub struct Ready<T>(Option<T>);
impl<T> Unpin for Ready<T> {}
impl<T> Future for Ready<T> {
type Output = T;
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
Poll::Ready(self.0.take().expect("`Ready` polled after completion"))
}
}
pub fn yield_now() -> YieldNow {
YieldNow(false)
}
#[derive(Debug)]
pub struct YieldNow(bool);
impl Future for YieldNow {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if !self.0 {
self.0 = true;
cx.waker().wake_by_ref();
Poll::Pending
} else {
Poll::Ready(())
}
}
}
pub fn join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> Join<Fut1, Fut2>
where
Fut1: Future,
Fut2: Future,
{
Join {
future1: future1,
output1: None,
future2: future2,
output2: None,
}
}
pin_project! {
#[derive(Debug)]
pub struct Join<Fut1, Fut2>
where
Fut1: Future,
Fut2: Future,
{
#[pin]
future1: Fut1,
output1: Option<Fut1::Output>,
#[pin]
future2: Fut2,
output2: Option<Fut2::Output>,
}
}
impl<Fut1, Fut2> Future for Join<Fut1, Fut2>
where
Fut1: Future,
Fut2: Future,
{
type Output = (Fut1::Output, Fut2::Output);
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
if this.output1.is_none() {
if let Poll::Ready(out) = this.future1.poll(cx) {
*this.output1 = Some(out);
}
}
if this.output2.is_none() {
if let Poll::Ready(out) = this.future2.poll(cx) {
*this.output2 = Some(out);
}
}
if this.output1.is_some() && this.output2.is_some() {
Poll::Ready((this.output1.take().unwrap(), this.output2.take().unwrap()))
} else {
Poll::Pending
}
}
}
pub fn try_join<T1, T2, E, Fut1, Fut2>(future1: Fut1, future2: Fut2) -> TryJoin<Fut1, Fut2>
where
Fut1: Future<Output = Result<T1, E>>,
Fut2: Future<Output = Result<T2, E>>,
{
TryJoin {
future1: future1,
output1: None,
future2: future2,
output2: None,
}
}
pin_project! {
#[derive(Debug)]
pub struct TryJoin<Fut1, Fut2>
where
Fut1: Future,
Fut2: Future,
{
#[pin]
future1: Fut1,
output1: Option<Fut1::Output>,
#[pin]
future2: Fut2,
output2: Option<Fut2::Output>,
}
}
impl<T1, T2, E, Fut1, Fut2> Future for TryJoin<Fut1, Fut2>
where
Fut1: Future<Output = Result<T1, E>>,
Fut2: Future<Output = Result<T2, E>>,
{
type Output = Result<(T1, T2), E>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
if this.output1.is_none() {
if let Poll::Ready(out) = this.future1.poll(cx) {
match out {
Ok(t) => *this.output1 = Some(Ok(t)),
Err(err) => return Poll::Ready(Err(err)),
}
}
}
if this.output2.is_none() {
if let Poll::Ready(out) = this.future2.poll(cx) {
match out {
Ok(t) => *this.output2 = Some(Ok(t)),
Err(err) => return Poll::Ready(Err(err)),
}
}
}
if this.output1.is_some() && this.output2.is_some() {
let res1 = this.output1.take().unwrap();
let res2 = this.output2.take().unwrap();
let t1 = res1.map_err(|_| unreachable!()).unwrap();
let t2 = res2.map_err(|_| unreachable!()).unwrap();
Poll::Ready(Ok((t1, t2)))
} else {
Poll::Pending
}
}
}