//! A symmetric either future. use core::{ future::Future, pin::Pin, task::{Context, Poll}, }; use pin_project_lite::pin_project; pin_project! { /// Combines two different futures that have the same output type. /// /// Construct variants with [`Either::left`] and [`Either::right`]. /// /// # Examples /// ``` /// use actix_utils::future::{ready, Ready, Either}; /// /// # async fn run() { /// let res = Either::<_, Ready>::left(ready(42)); /// assert_eq!(res.await, 42); /// /// let res = Either::, _>::right(ready(43)); /// assert_eq!(res.await, 43); /// # } /// ``` #[project = EitherProj] #[derive(Debug, Clone)] pub enum Either { /// A value of type `L`. #[allow(missing_docs)] Left { #[pin] value: L }, /// A value of type `R`. #[allow(missing_docs)] Right { #[pin] value: R }, } } impl Either { /// Creates new `Either` using left variant. pub fn left(value: L) -> Either { Either::Left { value } } /// Creates new `Either` using right variant. pub fn right(value: R) -> Either { Either::Right { value } } } impl Either { /// Unwraps into inner value when left and right have a common type. pub fn into_inner(self) -> T { match self { Either::Left { value } => value, Either::Right { value } => value, } } } impl Future for Either where L: Future, R: Future, { type Output = L::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match self.project() { EitherProj::Left { value } => value.poll(cx), EitherProj::Right { value } => value.poll(cx), } } } #[cfg(test)] mod tests { use super::*; use crate::future::{ready, Ready}; #[actix_rt::test] async fn test_either() { let res = Either::<_, Ready>::left(ready(42)); assert_eq!(res.await, 42); let res = Either::, _>::right(ready(43)); assert_eq!(res.await, 43); } }