ntex_util/future/
either.rsuse std::{error, fmt, future::Future, pin::Pin, task::Context, task::Poll};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Either<A, B> {
Left(A),
Right(B),
}
impl<A, B> Either<A, B> {
fn project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
unsafe {
match self.get_unchecked_mut() {
Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
}
}
}
#[inline]
pub fn is_left(&self) -> bool {
match *self {
Either::Left(_) => true,
Either::Right(_) => false,
}
}
#[inline]
pub fn is_right(&self) -> bool {
!self.is_left()
}
#[inline]
pub fn left(self) -> Option<A> {
match self {
Either::Left(l) => Some(l),
Either::Right(_) => None,
}
}
#[inline]
pub fn right(self) -> Option<B> {
match self {
Either::Left(_) => None,
Either::Right(r) => Some(r),
}
}
#[inline]
pub fn as_ref(&self) -> Either<&A, &B> {
match *self {
Either::Left(ref inner) => Either::Left(inner),
Either::Right(ref inner) => Either::Right(inner),
}
}
#[inline]
pub fn as_mut(&mut self) -> Either<&mut A, &mut B> {
match *self {
Either::Left(ref mut inner) => Either::Left(inner),
Either::Right(ref mut inner) => Either::Right(inner),
}
}
}
impl<T> Either<T, T> {
#[inline]
pub fn into_inner(self) -> T {
match self {
Either::Left(x) => x,
Either::Right(x) => x,
}
}
}
impl<A, B> error::Error for Either<A, B>
where
A: error::Error,
B: error::Error,
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Either::Left(a) => a.source(),
Either::Right(b) => b.source(),
}
}
}
impl<A, B> fmt::Display for Either<A, B>
where
A: fmt::Display,
B: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Either::Left(a) => a.fmt(f),
Either::Right(b) => b.fmt(f),
}
}
}
impl<A, B> Future for Either<A, B>
where
A: Future,
B: Future<Output = A::Output>,
{
type Output = A::Output;
#[inline]
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.project() {
Either::Left(x) => x.poll(cx),
Either::Right(x) => x.poll(cx),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
#[allow(clippy::unit_cmp)]
fn either() {
let mut e = Either::<(), ()>::Left(());
assert!(e.is_left());
assert!(!e.is_right());
assert!(e.left().is_some());
assert!(e.right().is_none());
e.as_ref();
e.as_mut();
let mut e = Either::<(), ()>::Right(());
assert!(!e.is_left());
assert!(e.is_right());
assert!(e.left().is_none());
assert!(e.right().is_some());
e.as_ref();
e.as_mut();
assert_eq!(Either::<(), ()>::Left(()).into_inner(), ());
assert_eq!(Either::<(), ()>::Right(()).into_inner(), ());
assert_eq!(
format!("{}", Either::<_, &'static str>::Left("test")),
"test"
);
assert_eq!(
format!("{}", Either::<&'static str, _>::Right("test")),
"test"
);
}
}