Skip to main content

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<T> Either<T, T> {
35    #[inline]
36    pub fn into_inner(self) -> T {
37        match self {
38            Either::Left(left) => left,
39            Either::Right(right) => right,
40        }
41    }
42}
43
44impl<L: fmt::Display, R: fmt::Display> fmt::Display for Either<L, R> {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match self {
47            Either::Left(l) => write!(f, "{l}"),
48            Either::Right(r) => write!(f, "{r}"),
49        }
50    }
51}
52
53impl<L: Error, R: Error> Error for Either<L, R> {}
54impl<I, L: Iterator<Item = I>, R: Iterator<Item = I>> Iterator for Either<L, R> {
55    type Item = I;
56
57    fn next(&mut self) -> Option<Self::Item> {
58        match self {
59            Either::Left(l) => l.next(),
60            Either::Right(r) => r.next(),
61        }
62    }
63}
64
65impl<I, L: Future<Output = I>, R: Future<Output = I>> Future for Either<L, R> {
66    type Output = I;
67
68    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
69        match unsafe { self.get_unchecked_mut() } {
70            Either::Left(l) => unsafe { Pin::new_unchecked(l) }.poll(cx),
71            Either::Right(r) => unsafe { Pin::new_unchecked(r) }.poll(cx),
72        }
73    }
74}
75
76impl<I, L: Stream<Item = I>, R: Stream<Item = I>> Stream for Either<L, R> {
77    type Item = I;
78
79    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
80        match unsafe { self.get_unchecked_mut() } {
81            Either::Left(l) => unsafe { Pin::new_unchecked(l) }.poll_next(cx),
82            Either::Right(r) => unsafe { Pin::new_unchecked(r) }.poll_next(cx),
83        }
84    }
85}