use std::{pin::Pin, task::ready};
#[inline]
pub fn then<F, M, F2>(f: F, map: M) -> Then<F, M, F2>
where
F: Future,
M: FnOnce(F::Output) -> F2,
F2: Future,
{
Then { phase: Phase::F1(f), map: Some(map) }
}
#[derive(Debug)]
pub struct Then<F, M, F2> {
phase: Phase<F, F2>,
map: Option<M>,
}
#[derive(Debug)]
enum Phase<F, F2> {
F1(F),
F2(F2),
}
impl<F, M, F2> Future for Then<F, M, F2>
where
F: Future,
M: FnOnce(F::Output) -> F2,
F2: Future,
{
type Output = F2::Output;
#[inline]
fn poll(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
let me = unsafe { self.as_mut().get_unchecked_mut() };
match &mut me.phase {
Phase::F1(f) => {
let f = unsafe { Pin::new_unchecked(f) };
let ok = ready!(f.poll(cx));
let ok = me.map.take().expect("poll after complete")(ok);
me.phase = Phase::F2(ok);
self.poll(cx)
}
Phase::F2(f) => unsafe { Pin::new_unchecked(f) }.poll(cx),
}
}
}