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