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#[derive(Debug, Clone)]
28pub enum Either<A, B> {
29 Left(A),
31 Right(B),
33}
34
35impl<A, B> Either<A, B> {
36 fn project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
37 unsafe {
38 match self.get_unchecked_mut() {
39 Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
40 Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
41 }
42 }
43 }
44}
45
46impl<A, B, T> Either<(T, A), (T, B)> {
47 pub fn factor_first(self) -> (T, Either<A, B>) {
51 match self {
52 Either::Left((x, a)) => (x, Either::Left(a)),
53 Either::Right((x, b)) => (x, Either::Right(b)),
54 }
55 }
56}
57
58impl<A, B, T> Either<(A, T), (B, T)> {
59 pub fn factor_second(self) -> (Either<A, B>, T) {
63 match self {
64 Either::Left((a, x)) => (Either::Left(a), x),
65 Either::Right((b, x)) => (Either::Right(b), x),
66 }
67 }
68}
69
70impl<T> Either<T, T> {
71 pub fn into_inner(self) -> T {
73 match self {
74 Either::Left(x) => x,
75 Either::Right(x) => x,
76 }
77 }
78}
79
80impl<A, B> Future for Either<A, B>
81where
82 A: Future,
83 B: Future<Output = A::Output>,
84{
85 type Output = A::Output;
86
87 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
88 match self.project() {
89 Either::Left(x) => x.poll(cx),
90 Either::Right(x) => x.poll(cx),
91 }
92 }
93}
94
95impl<A, B> FusedFuture for Either<A, B>
96where
97 A: FusedFuture,
98 B: FusedFuture<Output = A::Output>,
99{
100 fn is_terminated(&self) -> bool {
101 match self {
102 Either::Left(x) => x.is_terminated(),
103 Either::Right(x) => x.is_terminated(),
104 }
105 }
106}
107
108impl<A, B> Stream for Either<A, B>
109where
110 A: Stream,
111 B: Stream<Item = A::Item>,
112{
113 type Item = A::Item;
114
115 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
116 match self.project() {
117 Either::Left(x) => x.poll_next(cx),
118 Either::Right(x) => x.poll_next(cx),
119 }
120 }
121
122 fn size_hint(&self) -> (usize, Option<usize>) {
123 match self {
124 Either::Left(x) => x.size_hint(),
125 Either::Right(x) => x.size_hint(),
126 }
127 }
128}
129
130impl<A, B> FusedStream for Either<A, B>
131where
132 A: FusedStream,
133 B: FusedStream<Item = A::Item>,
134{
135 fn is_terminated(&self) -> bool {
136 match self {
137 Either::Left(x) => x.is_terminated(),
138 Either::Right(x) => x.is_terminated(),
139 }
140 }
141}
142
143#[cfg(feature = "sink")]
144impl<A, B, Item> Sink<Item> for Either<A, B>
145where
146 A: Sink<Item>,
147 B: Sink<Item, Error = A::Error>,
148{
149 type Error = A::Error;
150
151 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
152 match self.project() {
153 Either::Left(x) => x.poll_ready(cx),
154 Either::Right(x) => x.poll_ready(cx),
155 }
156 }
157
158 fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
159 match self.project() {
160 Either::Left(x) => x.start_send(item),
161 Either::Right(x) => x.start_send(item),
162 }
163 }
164
165 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
166 match self.project() {
167 Either::Left(x) => x.poll_flush(cx),
168 Either::Right(x) => x.poll_flush(cx),
169 }
170 }
171
172 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
173 match self.project() {
174 Either::Left(x) => x.poll_close(cx),
175 Either::Right(x) => x.poll_close(cx),
176 }
177 }
178}
179
180#[cfg(feature = "io")]
181#[cfg(feature = "std")]
182mod if_std {
183 use super::*;
184
185 use core::pin::Pin;
186 use core::task::{Context, Poll};
187 use futures_io::{
188 AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, Result, SeekFrom,
189 };
190
191 impl<A, B> AsyncRead for Either<A, B>
192 where
193 A: AsyncRead,
194 B: AsyncRead,
195 {
196 fn poll_read(
197 self: Pin<&mut Self>,
198 cx: &mut Context<'_>,
199 buf: &mut [u8],
200 ) -> Poll<Result<usize>> {
201 match self.project() {
202 Either::Left(x) => x.poll_read(cx, buf),
203 Either::Right(x) => x.poll_read(cx, buf),
204 }
205 }
206
207 fn poll_read_vectored(
208 self: Pin<&mut Self>,
209 cx: &mut Context<'_>,
210 bufs: &mut [IoSliceMut<'_>],
211 ) -> Poll<Result<usize>> {
212 match self.project() {
213 Either::Left(x) => x.poll_read_vectored(cx, bufs),
214 Either::Right(x) => x.poll_read_vectored(cx, bufs),
215 }
216 }
217 }
218
219 impl<A, B> AsyncWrite for Either<A, B>
220 where
221 A: AsyncWrite,
222 B: AsyncWrite,
223 {
224 fn poll_write(
225 self: Pin<&mut Self>,
226 cx: &mut Context<'_>,
227 buf: &[u8],
228 ) -> Poll<Result<usize>> {
229 match self.project() {
230 Either::Left(x) => x.poll_write(cx, buf),
231 Either::Right(x) => x.poll_write(cx, buf),
232 }
233 }
234
235 fn poll_write_vectored(
236 self: Pin<&mut Self>,
237 cx: &mut Context<'_>,
238 bufs: &[IoSlice<'_>],
239 ) -> Poll<Result<usize>> {
240 match self.project() {
241 Either::Left(x) => x.poll_write_vectored(cx, bufs),
242 Either::Right(x) => x.poll_write_vectored(cx, bufs),
243 }
244 }
245
246 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
247 match self.project() {
248 Either::Left(x) => x.poll_flush(cx),
249 Either::Right(x) => x.poll_flush(cx),
250 }
251 }
252
253 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
254 match self.project() {
255 Either::Left(x) => x.poll_close(cx),
256 Either::Right(x) => x.poll_close(cx),
257 }
258 }
259 }
260
261 impl<A, B> AsyncSeek for Either<A, B>
262 where
263 A: AsyncSeek,
264 B: AsyncSeek,
265 {
266 fn poll_seek(
267 self: Pin<&mut Self>,
268 cx: &mut Context<'_>,
269 pos: SeekFrom,
270 ) -> Poll<Result<u64>> {
271 match self.project() {
272 Either::Left(x) => x.poll_seek(cx, pos),
273 Either::Right(x) => x.poll_seek(cx, pos),
274 }
275 }
276 }
277
278 impl<A, B> AsyncBufRead for Either<A, B>
279 where
280 A: AsyncBufRead,
281 B: AsyncBufRead,
282 {
283 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
284 match self.project() {
285 Either::Left(x) => x.poll_fill_buf(cx),
286 Either::Right(x) => x.poll_fill_buf(cx),
287 }
288 }
289
290 fn consume(self: Pin<&mut Self>, amt: usize) {
291 match self.project() {
292 Either::Left(x) => x.consume(amt),
293 Either::Right(x) => x.consume(amt),
294 }
295 }
296 }
297}