use core::future::Future;
use core::mem;
use core::pin::Pin;
use core::task::{ready, Context, Poll};
#[derive(Debug)]
pub(crate) enum MaybeDone<Fut: Future> {
Future(Fut),
Done(Fut::Output),
Gone,
}
impl<Fut: Future> MaybeDone<Fut> {
pub(crate) fn new(future: Fut) -> MaybeDone<Fut> {
Self::Future(future)
}
}
impl<T, E, Fut> MaybeDone<Fut>
where
Fut: Future<Output = Result<T, E>>,
{
#[inline]
pub(crate) fn take_ok(self: Pin<&mut Self>) -> Option<T> {
let this = unsafe { self.get_unchecked_mut() };
match this {
MaybeDone::Done(Ok(_)) => {}
MaybeDone::Done(Err(_)) | MaybeDone::Future(_) | MaybeDone::Gone => return None,
}
match mem::replace(this, MaybeDone::Gone) {
MaybeDone::Done(Ok(output)) => Some(output),
_ => unreachable!(),
}
}
#[inline]
pub(crate) fn take_err(self: Pin<&mut Self>) -> Option<E> {
let this = unsafe { self.get_unchecked_mut() };
match this {
MaybeDone::Done(Err(_)) => {}
MaybeDone::Done(Ok(_)) | MaybeDone::Future(_) | MaybeDone::Gone => return None,
}
match mem::replace(this, MaybeDone::Gone) {
MaybeDone::Done(Err(output)) => Some(output),
_ => unreachable!(),
}
}
}
impl<Fut: Future> Future for MaybeDone<Fut> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let res = unsafe {
match Pin::as_mut(&mut self).get_unchecked_mut() {
MaybeDone::Future(a) => ready!(Pin::new_unchecked(a).poll(cx)),
MaybeDone::Done(_) => return Poll::Ready(()),
MaybeDone::Gone => panic!("MaybeDone polled after value taken"),
}
};
self.set(MaybeDone::Done(res));
Poll::Ready(())
}
}