use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
pub enum Either<A, B> {
Left(A),
Right(B),
}
impl<T> Either<T, T> {
pub fn into_inner(self) -> T {
match self {
Either::Left(v) | Either::Right(v) => v,
}
}
}
pin_project_lite::pin_project! {
pub struct Select<A, B> {
#[pin] a: A,
#[pin] b: B,
}
}
impl<A: Future, B: Future> Future for Select<A, B> {
type Output = Either<A::Output, B::Output>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
if let Poll::Ready(val) = this.a.poll(cx) {
return Poll::Ready(Either::Left(val));
}
if let Poll::Ready(val) = this.b.poll(cx) {
return Poll::Ready(Either::Right(val));
}
Poll::Pending
}
}
pub fn select<A: Future, B: Future>(a: A, b: B) -> Select<A, B> {
Select { a, b }
}
pub enum Either3<A, B, C> {
First(A),
Second(B),
Third(C),
}
impl<T> Either3<T, T, T> {
pub fn into_inner(self) -> T {
match self {
Either3::First(v) | Either3::Second(v) | Either3::Third(v) => v,
}
}
}
pin_project_lite::pin_project! {
pub struct Select3<A, B, C> {
#[pin] a: A,
#[pin] b: B,
#[pin] c: C,
}
}
impl<A: Future, B: Future, C: Future> Future for Select3<A, B, C> {
type Output = Either3<A::Output, B::Output, C::Output>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
if let Poll::Ready(val) = this.a.poll(cx) {
return Poll::Ready(Either3::First(val));
}
if let Poll::Ready(val) = this.b.poll(cx) {
return Poll::Ready(Either3::Second(val));
}
if let Poll::Ready(val) = this.c.poll(cx) {
return Poll::Ready(Either3::Third(val));
}
Poll::Pending
}
}
pub fn select3<A: Future, B: Future, C: Future>(a: A, b: B, c: C) -> Select3<A, B, C> {
Select3 { a, b, c }
}