flowly_core/
either.rs

1use std::{
2    error::Error,
3    fmt,
4    pin::Pin,
5    task::{Context, Poll},
6};
7
8use futures::Stream;
9
10#[derive(Debug, Clone, Copy, PartialEq)]
11pub enum Either<L, R = L> {
12    Left(L),
13    Right(R),
14}
15
16impl<L, R> Either<L, R> {
17    #[inline]
18    pub fn into_left(self) -> L {
19        match self {
20            Either::Left(left) => left,
21            Either::Right(_) => unreachable!(),
22        }
23    }
24
25    #[inline]
26    pub fn into_right(self) -> R {
27        match self {
28            Either::Left(_) => unreachable!(),
29            Either::Right(right) => right,
30        }
31    }
32}
33
34impl<L: fmt::Display, R: fmt::Display> fmt::Display for Either<L, R> {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        match self {
37            Either::Left(l) => write!(f, "{l}"),
38            Either::Right(r) => write!(f, "{r}"),
39        }
40    }
41}
42
43impl<L: Error, R: Error> Error for Either<L, R> {}
44impl<I, L: Iterator<Item = I>, R: Iterator<Item = I>> Iterator for Either<L, R> {
45    type Item = I;
46
47    fn next(&mut self) -> Option<Self::Item> {
48        match self {
49            Either::Left(l) => l.next(),
50            Either::Right(r) => r.next(),
51        }
52    }
53}
54
55impl<I, L: Future<Output = I>, R: Future<Output = I>> Future for Either<L, R> {
56    type Output = I;
57
58    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
59        match unsafe { self.get_unchecked_mut() } {
60            Either::Left(l) => unsafe { Pin::new_unchecked(l) }.poll(cx),
61            Either::Right(r) => unsafe { Pin::new_unchecked(r) }.poll(cx),
62        }
63    }
64}
65
66impl<I, L: Stream<Item = I>, R: Stream<Item = I>> Stream for Either<L, R> {
67    type Item = I;
68
69    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
70        match unsafe { self.get_unchecked_mut() } {
71            Either::Left(l) => unsafe { Pin::new_unchecked(l) }.poll_next(cx),
72            Either::Right(r) => unsafe { Pin::new_unchecked(r) }.poll_next(cx),
73        }
74    }
75}