pub use either::Either;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
pub mod futs {
pub struct Either<L, R> {
pub(super) left: L,
pub(super) right: R,
}
#[cfg(feature = "fair")]
#[cfg_attr(docsrs, doc(cfg(feature = "fair")))]
pub struct EitherFair<L, R> {
pub(super) left: L,
pub(super) right: R,
}
pub struct TryEither<L, R> {
pub(super) fut: Either<L, R>,
}
#[cfg(feature = "fair")]
#[cfg_attr(docsrs, doc(cfg(feature = "fair")))]
pub struct TryEitherFair<L, R> {
pub(super) fut: EitherFair<L, R>,
}
}
pub fn either<L, R>(left: L, right: R) -> futs::Either<L, R>
where
L: Future,
R: Future,
{
futs::Either { left, right }
}
#[cfg(feature = "fair")]
#[cfg_attr(docsrs, doc(cfg(feature = "fair")))]
pub fn either_fair<L, R>(left: L, right: R) -> futs::EitherFair<L, R>
where
L: Future,
R: Future,
{
futs::EitherFair { left, right }
}
pub fn try_either<OL, OR, E, L, R>(left: L, right: R) -> futs::TryEither<L, R>
where
L: Future<Output = Result<OL, E>>,
R: Future<Output = Result<OR, E>>,
{
futs::TryEither { fut: either(left, right), }
}
#[cfg(feature = "fair")]
#[cfg_attr(docsrs, doc(cfg(feature = "fair")))]
pub fn try_either_fair<OL, OR, E, L, R>(left: L, right: R) -> futs::TryEitherFair<L, R>
where
L: Future<Output = Result<OL, E>>,
R: Future<Output = Result<OR, E>>,
{
futs::TryEitherFair { fut: either_fair(left, right), }
}
impl<L, R> Future for futs::Either<L, R>
where
L: Future,
R: Future,
{
type Output = Either<L::Output, R::Output>;
fn poll(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> {
let this = unsafe { self.get_unchecked_mut() };
if let Poll::Ready(out) = unsafe { Pin::new_unchecked(&mut this.left) }.poll(ctx) {
return Poll::Ready(Either::Left(out));
}
if let Poll::Ready(out) = unsafe { Pin::new_unchecked(&mut this.right) }.poll(ctx) {
return Poll::Ready(Either::Right(out));
}
Poll::Pending
}
}
#[cfg(feature = "fair")]
impl<L, R> Future for futs::EitherFair<L, R>
where
L: Future,
R: Future,
{
type Output = Either<L::Output, R::Output>;
fn poll(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> {
let this = unsafe { self.get_unchecked_mut() };
if fastrand::bool() {
if let Poll::Ready(out) = unsafe { Pin::new_unchecked(&mut this.left) }.poll(ctx) {
return Poll::Ready(Either::Left(out));
}
if let Poll::Ready(out) = unsafe { Pin::new_unchecked(&mut this.right) }.poll(ctx) {
return Poll::Ready(Either::Right(out));
}
} else {
if let Poll::Ready(out) = unsafe { Pin::new_unchecked(&mut this.right) }.poll(ctx) {
return Poll::Ready(Either::Right(out));
}
if let Poll::Ready(out) = unsafe { Pin::new_unchecked(&mut this.left) }.poll(ctx) {
return Poll::Ready(Either::Left(out));
}
}
Poll::Pending
}
}
impl<OL, OR, E, L, R> Future for futs::TryEither<L, R>
where
L: Future<Output = Result<OL, E>>,
R: Future<Output = Result<OR, E>>,
{
type Output = Result<Either<OL, OR>, E>;
fn poll(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> {
let this = unsafe { self.get_unchecked_mut() };
if let Poll::Ready(out) = unsafe { Pin::new_unchecked(&mut this.fut) }.poll(ctx) {
match out {
Either::Left(Ok(left)) => Ok(Either::Left(left)),
Either::Right(Ok(right)) => Ok(Either::Right(right)),
Either::Left(Err(err)) | Either::Right(Err(err)) => Err(err),
}.into()
} else {
Poll::Pending
}
}
}
#[cfg(feature = "fair")]
impl<OL, OR, E, L, R> Future for futs::TryEitherFair<L, R>
where
L: Future<Output = Result<OL, E>>,
R: Future<Output = Result<OR, E>>,
{
type Output = Result<Either<OL, OR>, E>;
fn poll(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> {
let this = unsafe { self.get_unchecked_mut() };
if let Poll::Ready(out) = unsafe { Pin::new_unchecked(&mut this.fut) }.poll(ctx) {
match out {
Either::Left(Ok(left)) => Ok(Either::Left(left)),
Either::Right(Ok(right)) => Ok(Either::Right(right)),
Either::Left(Err(err)) | Either::Right(Err(err)) => Err(err),
}.into()
} else {
Poll::Pending
}
}
}