use core::future::Future;
pub enum Either<A, B> {
First(A),
Second(B),
}
impl<A> Either<A, core::convert::Infallible> {
pub fn ignore_never_b(self) -> A {
match self {
Self::First(a) => a,
Self::Second(b) => match b {},
}
}
}
impl<B> Either<core::convert::Infallible, B> {
pub fn ignore_never_a(self) -> B {
match self {
Self::First(a) => match a {},
Self::Second(b) => b,
}
}
}
impl<A, B> Either<A, B> {
pub fn first_is_error(self) -> Result<B, A> {
match self {
Either::First(a) => Err(a),
Either::Second(b) => Ok(b),
}
}
}
pub(crate) async fn select_either<A: Future, B: Future>(
a: A,
b: B,
) -> Either<A::Output, B::Output> {
let mut a = core::pin::pin!(a);
let mut b = core::pin::pin!(b);
core::future::poll_fn(|cx| {
use core::task::Poll;
match a.as_mut().poll(cx) {
Poll::Ready(output) => return Poll::Ready(Either::First(output)),
Poll::Pending => (),
}
match b.as_mut().poll(cx) {
Poll::Ready(output) => return Poll::Ready(Either::Second(output)),
Poll::Pending => (),
}
Poll::Pending
})
.await
}
pub(crate) async fn select<A: Future, B: Future<Output = A::Output>>(a: A, b: B) -> A::Output {
match select_either(a, b).await {
Either::First(output) | Either::Second(output) => output,
}
}
#[cfg(test)]
mod tests {
use core::future::pending;
use futures_util::FutureExt;
use super::select;
struct Success;
#[test]
#[ntest::timeout(1000)]
fn select_first() {
let Success = select(async { Success }, pending())
.now_or_never()
.expect("Future must resolve");
}
#[test]
#[ntest::timeout(1000)]
fn select_second() {
let Success = select(pending(), async { Success })
.now_or_never()
.expect("Future must resolve");
}
#[test]
#[ntest::timeout(1000)]
fn select_neither() {
enum Never {}
assert!(select(pending::<Never>(), pending::<Never>())
.now_or_never()
.is_none());
}
}