futures_util/future/
either.rs

1use core::pin::Pin;
2use core::task::{Context, Poll};
3use futures_core::future::{FusedFuture, Future};
4use futures_core::stream::{FusedStream, Stream};
5#[cfg(feature = "sink")]
6use futures_sink::Sink;
7
8/// Combines two different futures, streams, or sinks having the same associated types into a single type.
9///
10/// This is useful when conditionally choosing between two distinct future types:
11///
12/// ```rust
13/// use futures::future::Either;
14///
15/// # futures::executor::block_on(async {
16/// let cond = true;
17///
18/// let fut = if cond {
19///     Either::Left(async move { 12 })
20/// } else {
21///     Either::Right(async move { 44 })
22/// };
23///
24/// assert_eq!(fut.await, 12);
25/// # })
26/// ```
27#[derive(Debug, Clone)]
28pub enum Either<A, B> {
29    /// First branch of the type
30    Left(/* #[pin] */ A),
31    /// Second branch of the type
32    Right(/* #[pin] */ B),
33}
34
35impl<A, B> Either<A, B> {
36    /// Convert `Pin<&Either<A, B>>` to `Either<Pin<&A>, Pin<&B>>`,
37    /// pinned projections of the inner variants.
38    pub fn as_pin_ref(self: Pin<&Self>) -> Either<Pin<&A>, Pin<&B>> {
39        // SAFETY: We can use `new_unchecked` because the `inner` parts are
40        // guaranteed to be pinned, as they come from `self` which is pinned.
41        unsafe {
42            match self.get_ref() {
43                Self::Left(inner) => Either::Left(Pin::new_unchecked(inner)),
44                Self::Right(inner) => Either::Right(Pin::new_unchecked(inner)),
45            }
46        }
47    }
48
49    /// Convert `Pin<&mut Either<A, B>>` to `Either<Pin<&mut A>, Pin<&mut B>>`,
50    /// pinned projections of the inner variants.
51    pub fn as_pin_mut(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
52        // SAFETY: `get_unchecked_mut` is fine because we don't move anything.
53        // We can use `new_unchecked` because the `inner` parts are guaranteed
54        // to be pinned, as they come from `self` which is pinned, and we never
55        // offer an unpinned `&mut A` or `&mut B` through `Pin<&mut Self>`. We
56        // also don't have an implementation of `Drop`, nor manual `Unpin`.
57        unsafe {
58            match self.get_unchecked_mut() {
59                Self::Left(inner) => Either::Left(Pin::new_unchecked(inner)),
60                Self::Right(inner) => Either::Right(Pin::new_unchecked(inner)),
61            }
62        }
63    }
64}
65
66impl<A, B, T> Either<(T, A), (T, B)> {
67    /// Factor out a homogeneous type from an either of pairs.
68    ///
69    /// Here, the homogeneous type is the first element of the pairs.
70    pub fn factor_first(self) -> (T, Either<A, B>) {
71        match self {
72            Self::Left((x, a)) => (x, Either::Left(a)),
73            Self::Right((x, b)) => (x, Either::Right(b)),
74        }
75    }
76}
77
78impl<A, B, T> Either<(A, T), (B, T)> {
79    /// Factor out a homogeneous type from an either of pairs.
80    ///
81    /// Here, the homogeneous type is the second element of the pairs.
82    pub fn factor_second(self) -> (Either<A, B>, T) {
83        match self {
84            Self::Left((a, x)) => (Either::Left(a), x),
85            Self::Right((b, x)) => (Either::Right(b), x),
86        }
87    }
88}
89
90impl<T> Either<T, T> {
91    /// Extract the value of an either over two equivalent types.
92    pub fn into_inner(self) -> T {
93        match self {
94            Self::Left(x) | Self::Right(x) => x,
95        }
96    }
97}
98
99impl<A, B> Future for Either<A, B>
100where
101    A: Future,
102    B: Future<Output = A::Output>,
103{
104    type Output = A::Output;
105
106    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
107        match self.as_pin_mut() {
108            Either::Left(x) => x.poll(cx),
109            Either::Right(x) => x.poll(cx),
110        }
111    }
112}
113
114impl<A, B> FusedFuture for Either<A, B>
115where
116    A: FusedFuture,
117    B: FusedFuture<Output = A::Output>,
118{
119    fn is_terminated(&self) -> bool {
120        match self {
121            Self::Left(x) => x.is_terminated(),
122            Self::Right(x) => x.is_terminated(),
123        }
124    }
125}
126
127impl<A, B> Stream for Either<A, B>
128where
129    A: Stream,
130    B: Stream<Item = A::Item>,
131{
132    type Item = A::Item;
133
134    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
135        match self.as_pin_mut() {
136            Either::Left(x) => x.poll_next(cx),
137            Either::Right(x) => x.poll_next(cx),
138        }
139    }
140
141    fn size_hint(&self) -> (usize, Option<usize>) {
142        match self {
143            Self::Left(x) => x.size_hint(),
144            Self::Right(x) => x.size_hint(),
145        }
146    }
147}
148
149impl<A, B> FusedStream for Either<A, B>
150where
151    A: FusedStream,
152    B: FusedStream<Item = A::Item>,
153{
154    fn is_terminated(&self) -> bool {
155        match self {
156            Self::Left(x) => x.is_terminated(),
157            Self::Right(x) => x.is_terminated(),
158        }
159    }
160}
161
162#[cfg(feature = "sink")]
163impl<A, B, Item> Sink<Item> for Either<A, B>
164where
165    A: Sink<Item>,
166    B: Sink<Item, Error = A::Error>,
167{
168    type Error = A::Error;
169
170    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
171        match self.as_pin_mut() {
172            Either::Left(x) => x.poll_ready(cx),
173            Either::Right(x) => x.poll_ready(cx),
174        }
175    }
176
177    fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
178        match self.as_pin_mut() {
179            Either::Left(x) => x.start_send(item),
180            Either::Right(x) => x.start_send(item),
181        }
182    }
183
184    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
185        match self.as_pin_mut() {
186            Either::Left(x) => x.poll_flush(cx),
187            Either::Right(x) => x.poll_flush(cx),
188        }
189    }
190
191    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
192        match self.as_pin_mut() {
193            Either::Left(x) => x.poll_close(cx),
194            Either::Right(x) => x.poll_close(cx),
195        }
196    }
197}
198
199#[cfg(feature = "io")]
200#[cfg(feature = "std")]
201mod if_std {
202    use super::*;
203
204    use futures_io::{
205        AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, Result, SeekFrom,
206    };
207
208    impl<A, B> AsyncRead for Either<A, B>
209    where
210        A: AsyncRead,
211        B: AsyncRead,
212    {
213        fn poll_read(
214            self: Pin<&mut Self>,
215            cx: &mut Context<'_>,
216            buf: &mut [u8],
217        ) -> Poll<Result<usize>> {
218            match self.as_pin_mut() {
219                Either::Left(x) => x.poll_read(cx, buf),
220                Either::Right(x) => x.poll_read(cx, buf),
221            }
222        }
223
224        fn poll_read_vectored(
225            self: Pin<&mut Self>,
226            cx: &mut Context<'_>,
227            bufs: &mut [IoSliceMut<'_>],
228        ) -> Poll<Result<usize>> {
229            match self.as_pin_mut() {
230                Either::Left(x) => x.poll_read_vectored(cx, bufs),
231                Either::Right(x) => x.poll_read_vectored(cx, bufs),
232            }
233        }
234    }
235
236    impl<A, B> AsyncWrite for Either<A, B>
237    where
238        A: AsyncWrite,
239        B: AsyncWrite,
240    {
241        fn poll_write(
242            self: Pin<&mut Self>,
243            cx: &mut Context<'_>,
244            buf: &[u8],
245        ) -> Poll<Result<usize>> {
246            match self.as_pin_mut() {
247                Either::Left(x) => x.poll_write(cx, buf),
248                Either::Right(x) => x.poll_write(cx, buf),
249            }
250        }
251
252        fn poll_write_vectored(
253            self: Pin<&mut Self>,
254            cx: &mut Context<'_>,
255            bufs: &[IoSlice<'_>],
256        ) -> Poll<Result<usize>> {
257            match self.as_pin_mut() {
258                Either::Left(x) => x.poll_write_vectored(cx, bufs),
259                Either::Right(x) => x.poll_write_vectored(cx, bufs),
260            }
261        }
262
263        fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
264            match self.as_pin_mut() {
265                Either::Left(x) => x.poll_flush(cx),
266                Either::Right(x) => x.poll_flush(cx),
267            }
268        }
269
270        fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
271            match self.as_pin_mut() {
272                Either::Left(x) => x.poll_close(cx),
273                Either::Right(x) => x.poll_close(cx),
274            }
275        }
276    }
277
278    impl<A, B> AsyncSeek for Either<A, B>
279    where
280        A: AsyncSeek,
281        B: AsyncSeek,
282    {
283        fn poll_seek(
284            self: Pin<&mut Self>,
285            cx: &mut Context<'_>,
286            pos: SeekFrom,
287        ) -> Poll<Result<u64>> {
288            match self.as_pin_mut() {
289                Either::Left(x) => x.poll_seek(cx, pos),
290                Either::Right(x) => x.poll_seek(cx, pos),
291            }
292        }
293    }
294
295    impl<A, B> AsyncBufRead for Either<A, B>
296    where
297        A: AsyncBufRead,
298        B: AsyncBufRead,
299    {
300        fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
301            match self.as_pin_mut() {
302                Either::Left(x) => x.poll_fill_buf(cx),
303                Either::Right(x) => x.poll_fill_buf(cx),
304            }
305        }
306
307        fn consume(self: Pin<&mut Self>, amt: usize) {
308            match self.as_pin_mut() {
309                Either::Left(x) => x.consume(amt),
310                Either::Right(x) => x.consume(amt),
311            }
312        }
313    }
314}