actix_utils/future/
either.rs

1//! A symmetric either future.
2
3use core::{
4    future::Future,
5    pin::Pin,
6    task::{Context, Poll},
7};
8
9use pin_project_lite::pin_project;
10
11pin_project! {
12    /// Combines two different futures that have the same output type.
13    ///
14    /// Construct variants with [`Either::left`] and [`Either::right`].
15    ///
16    /// # Examples
17    /// ```
18    /// use actix_utils::future::{ready, Ready, Either};
19    ///
20    /// # async fn run() {
21    /// let res = Either::<_, Ready<usize>>::left(ready(42));
22    /// assert_eq!(res.await, 42);
23    ///
24    /// let res = Either::<Ready<usize>, _>::right(ready(43));
25    /// assert_eq!(res.await, 43);
26    /// # }
27    /// ```
28    #[project = EitherProj]
29    #[derive(Debug, Clone)]
30    pub enum Either<L, R> {
31        /// A value of type `L`.
32        #[allow(missing_docs)]
33        Left { #[pin] value: L },
34
35        /// A value of type `R`.
36        #[allow(missing_docs)]
37        Right { #[pin] value: R },
38    }
39}
40
41impl<L, R> Either<L, R> {
42    /// Creates new `Either` using left variant.
43    #[inline]
44    pub fn left(value: L) -> Either<L, R> {
45        Either::Left { value }
46    }
47
48    /// Creates new `Either` using right variant.
49    #[inline]
50    pub fn right(value: R) -> Either<L, R> {
51        Either::Right { value }
52    }
53}
54
55impl<T> Either<T, T> {
56    /// Unwraps into inner value when left and right have a common type.
57    #[inline]
58    pub fn into_inner(self) -> T {
59        match self {
60            Either::Left { value } => value,
61            Either::Right { value } => value,
62        }
63    }
64}
65
66impl<L, R> Future for Either<L, R>
67where
68    L: Future,
69    R: Future<Output = L::Output>,
70{
71    type Output = L::Output;
72
73    #[inline]
74    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
75        match self.project() {
76            EitherProj::Left { value } => value.poll(cx),
77            EitherProj::Right { value } => value.poll(cx),
78        }
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use crate::future::{ready, Ready};
86
87    #[actix_rt::test]
88    async fn test_either() {
89        let res = Either::<_, Ready<usize>>::left(ready(42));
90        assert_eq!(res.await, 42);
91
92        let res = Either::<Ready<usize>, _>::right(ready(43));
93        assert_eq!(res.await, 43);
94    }
95}