Coverage Report

Created: 2024-09-08 06:35

/rust/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.21/src/future/either.rs
Line
Count
Source (jump to first uncovered line)
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 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)]
28
pub 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
35
impl<A, B> Either<A, B> {
36
210
    fn project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
37
210
        unsafe {
38
210
            match self.get_unchecked_mut() {
39
127
                Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
40
83
                Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
41
            }
42
        }
43
210
    }
Unexecuted instantiation: <futures_util::future::either::Either<_, _>>::project
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::punch_hole::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::punch_hole::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}>>::project
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::read_to_mem::{closure#0}::{closure#0}, core::result::Result<usize, disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::read_to_mem::{closure#0}::{closure#0}, core::result::Result<usize, disk::Error>>::{closure#3}>>::project
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::write_from_mem::{closure#0}::{closure#0}, core::result::Result<usize, disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::write_from_mem::{closure#0}::{closure#0}, core::result::Result<usize, disk::Error>>::{closure#3}>>::project
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::write_zeroes_at::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::write_zeroes_at::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}>>::project
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::flush::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::flush::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}>>::project
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::fsync::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::fsync::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}>>::project
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::fdatasync::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::fdatasync::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}>>::project
<futures_util::future::either::Either<futures_util::future::future::fuse::Fuse<core::future::pending::Pending<core::result::Result<(), anyhow::Error>>>, futures_util::future::future::fuse::Fuse<devices::virtio::async_utils::handle_irq_resample::{closure#0}>>>::project
Line
Count
Source
36
210
    fn project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
37
210
        unsafe {
38
210
            match self.get_unchecked_mut() {
39
127
                Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
40
83
                Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
41
            }
42
        }
43
210
    }
Unexecuted instantiation: <futures_util::future::either::Either<futures_util::future::future::fuse::Fuse<devices::virtio::vhost_user_frontend::sys::unix::run_backend_request_handler::{closure#0}>, futures_util::future::future::Map<futures_channel::oneshot::Receiver<()>, <devices::virtio::vhost_user_frontend::worker::Worker>::run::{closure#0}::{closure#0}>>>::project
44
}
45
46
impl<A, B, T> Either<(T, A), (T, B)> {
47
    /// Factor out a homogeneous type from an either of pairs.
48
    ///
49
    /// Here, the homogeneous type is the first element of the pairs.
50
0
    pub fn factor_first(self) -> (T, Either<A, B>) {
51
0
        match self {
52
0
            Either::Left((x, a)) => (x, Either::Left(a)),
53
0
            Either::Right((x, b)) => (x, Either::Right(b)),
54
        }
55
0
    }
56
}
57
58
impl<A, B, T> Either<(A, T), (B, T)> {
59
    /// Factor out a homogeneous type from an either of pairs.
60
    ///
61
    /// Here, the homogeneous type is the second element of the pairs.
62
0
    pub fn factor_second(self) -> (Either<A, B>, T) {
63
0
        match self {
64
0
            Either::Left((a, x)) => (Either::Left(a), x),
65
0
            Either::Right((b, x)) => (Either::Right(b), x),
66
        }
67
0
    }
68
}
69
70
impl<T> Either<T, T> {
71
    /// Extract the value of an either over two equivalent types.
72
0
    pub fn into_inner(self) -> T {
73
0
        match self {
74
0
            Either::Left(x) => x,
75
0
            Either::Right(x) => x,
76
        }
77
0
    }
78
}
79
80
impl<A, B> Future for Either<A, B>
81
where
82
    A: Future,
83
    B: Future<Output = A::Output>,
84
{
85
    type Output = A::Output;
86
87
210
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
88
210
        match self.project() {
89
127
            Either::Left(x) => x.poll(cx),
90
83
            Either::Right(x) => x.poll(cx),
91
        }
92
210
    }
Unexecuted instantiation: <futures_util::future::either::Either<_, _> as core::future::future::Future>::poll
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::punch_hole::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::punch_hole::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}> as core::future::future::Future>::poll
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::read_to_mem::{closure#0}::{closure#0}, core::result::Result<usize, disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::read_to_mem::{closure#0}::{closure#0}, core::result::Result<usize, disk::Error>>::{closure#3}> as core::future::future::Future>::poll
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::write_from_mem::{closure#0}::{closure#0}, core::result::Result<usize, disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::write_from_mem::{closure#0}::{closure#0}, core::result::Result<usize, disk::Error>>::{closure#3}> as core::future::future::Future>::poll
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::write_zeroes_at::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::write_zeroes_at::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}> as core::future::future::Future>::poll
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::flush::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::flush::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}> as core::future::future::Future>::poll
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::fsync::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::fsync::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}> as core::future::future::Future>::poll
Unexecuted instantiation: <futures_util::future::either::Either<<cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::fdatasync::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#0}, <cros_async::blocking::pool::Inner>::spawn<<disk::asynchronous::AsyncDiskFileWrapper<disk::qcow::QcowFile> as disk::AsyncDisk>::fdatasync::{closure#0}::{closure#0}, core::result::Result<(), disk::Error>>::{closure#3}> as core::future::future::Future>::poll
<futures_util::future::either::Either<futures_util::future::future::fuse::Fuse<core::future::pending::Pending<core::result::Result<(), anyhow::Error>>>, futures_util::future::future::fuse::Fuse<devices::virtio::async_utils::handle_irq_resample::{closure#0}>> as core::future::future::Future>::poll
Line
Count
Source
87
210
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
88
210
        match self.project() {
89
127
            Either::Left(x) => x.poll(cx),
90
83
            Either::Right(x) => x.poll(cx),
91
        }
92
210
    }
Unexecuted instantiation: <futures_util::future::either::Either<futures_util::future::future::fuse::Fuse<devices::virtio::vhost_user_frontend::sys::unix::run_backend_request_handler::{closure#0}>, futures_util::future::future::Map<futures_channel::oneshot::Receiver<()>, <devices::virtio::vhost_user_frontend::worker::Worker>::run::{closure#0}::{closure#0}>> as core::future::future::Future>::poll
93
}
94
95
impl<A, B> FusedFuture for Either<A, B>
96
where
97
    A: FusedFuture,
98
    B: FusedFuture<Output = A::Output>,
99
{
100
210
    fn is_terminated(&self) -> bool {
101
210
        match self {
102
127
            Either::Left(x) => x.is_terminated(),
103
83
            Either::Right(x) => x.is_terminated(),
104
        }
105
210
    }
Unexecuted instantiation: <futures_util::future::either::Either<_, _> as futures_core::future::FusedFuture>::is_terminated
<futures_util::future::either::Either<futures_util::future::future::fuse::Fuse<core::future::pending::Pending<core::result::Result<(), anyhow::Error>>>, futures_util::future::future::fuse::Fuse<devices::virtio::async_utils::handle_irq_resample::{closure#0}>> as futures_core::future::FusedFuture>::is_terminated
Line
Count
Source
100
210
    fn is_terminated(&self) -> bool {
101
210
        match self {
102
127
            Either::Left(x) => x.is_terminated(),
103
83
            Either::Right(x) => x.is_terminated(),
104
        }
105
210
    }
106
}
107
108
impl<A, B> Stream for Either<A, B>
109
where
110
    A: Stream,
111
    B: Stream<Item = A::Item>,
112
{
113
    type Item = A::Item;
114
115
0
    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
116
0
        match self.project() {
117
0
            Either::Left(x) => x.poll_next(cx),
118
0
            Either::Right(x) => x.poll_next(cx),
119
        }
120
0
    }
121
122
0
    fn size_hint(&self) -> (usize, Option<usize>) {
123
0
        match self {
124
0
            Either::Left(x) => x.size_hint(),
125
0
            Either::Right(x) => x.size_hint(),
126
        }
127
0
    }
128
}
129
130
impl<A, B> FusedStream for Either<A, B>
131
where
132
    A: FusedStream,
133
    B: FusedStream<Item = A::Item>,
134
{
135
0
    fn is_terminated(&self) -> bool {
136
0
        match self {
137
0
            Either::Left(x) => x.is_terminated(),
138
0
            Either::Right(x) => x.is_terminated(),
139
        }
140
0
    }
141
}
142
143
#[cfg(feature = "sink")]
144
impl<A, B, Item> Sink<Item> for Either<A, B>
145
where
146
    A: Sink<Item>,
147
    B: Sink<Item, Error = A::Error>,
148
{
149
    type Error = A::Error;
150
151
0
    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
152
0
        match self.project() {
153
0
            Either::Left(x) => x.poll_ready(cx),
154
0
            Either::Right(x) => x.poll_ready(cx),
155
        }
156
0
    }
157
158
0
    fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
159
0
        match self.project() {
160
0
            Either::Left(x) => x.start_send(item),
161
0
            Either::Right(x) => x.start_send(item),
162
        }
163
0
    }
164
165
0
    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
166
0
        match self.project() {
167
0
            Either::Left(x) => x.poll_flush(cx),
168
0
            Either::Right(x) => x.poll_flush(cx),
169
        }
170
0
    }
171
172
0
    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
173
0
        match self.project() {
174
0
            Either::Left(x) => x.poll_close(cx),
175
0
            Either::Right(x) => x.poll_close(cx),
176
        }
177
0
    }
178
}
179
180
#[cfg(feature = "io")]
181
#[cfg(feature = "std")]
182
mod 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
0
        fn poll_read(
197
0
            self: Pin<&mut Self>,
198
0
            cx: &mut Context<'_>,
199
0
            buf: &mut [u8],
200
0
        ) -> Poll<Result<usize>> {
201
0
            match self.project() {
202
0
                Either::Left(x) => x.poll_read(cx, buf),
203
0
                Either::Right(x) => x.poll_read(cx, buf),
204
            }
205
0
        }
206
207
0
        fn poll_read_vectored(
208
0
            self: Pin<&mut Self>,
209
0
            cx: &mut Context<'_>,
210
0
            bufs: &mut [IoSliceMut<'_>],
211
0
        ) -> Poll<Result<usize>> {
212
0
            match self.project() {
213
0
                Either::Left(x) => x.poll_read_vectored(cx, bufs),
214
0
                Either::Right(x) => x.poll_read_vectored(cx, bufs),
215
            }
216
0
        }
217
    }
218
219
    impl<A, B> AsyncWrite for Either<A, B>
220
    where
221
        A: AsyncWrite,
222
        B: AsyncWrite,
223
    {
224
0
        fn poll_write(
225
0
            self: Pin<&mut Self>,
226
0
            cx: &mut Context<'_>,
227
0
            buf: &[u8],
228
0
        ) -> Poll<Result<usize>> {
229
0
            match self.project() {
230
0
                Either::Left(x) => x.poll_write(cx, buf),
231
0
                Either::Right(x) => x.poll_write(cx, buf),
232
            }
233
0
        }
234
235
0
        fn poll_write_vectored(
236
0
            self: Pin<&mut Self>,
237
0
            cx: &mut Context<'_>,
238
0
            bufs: &[IoSlice<'_>],
239
0
        ) -> Poll<Result<usize>> {
240
0
            match self.project() {
241
0
                Either::Left(x) => x.poll_write_vectored(cx, bufs),
242
0
                Either::Right(x) => x.poll_write_vectored(cx, bufs),
243
            }
244
0
        }
245
246
0
        fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
247
0
            match self.project() {
248
0
                Either::Left(x) => x.poll_flush(cx),
249
0
                Either::Right(x) => x.poll_flush(cx),
250
            }
251
0
        }
252
253
0
        fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
254
0
            match self.project() {
255
0
                Either::Left(x) => x.poll_close(cx),
256
0
                Either::Right(x) => x.poll_close(cx),
257
            }
258
0
        }
259
    }
260
261
    impl<A, B> AsyncSeek for Either<A, B>
262
    where
263
        A: AsyncSeek,
264
        B: AsyncSeek,
265
    {
266
0
        fn poll_seek(
267
0
            self: Pin<&mut Self>,
268
0
            cx: &mut Context<'_>,
269
0
            pos: SeekFrom,
270
0
        ) -> Poll<Result<u64>> {
271
0
            match self.project() {
272
0
                Either::Left(x) => x.poll_seek(cx, pos),
273
0
                Either::Right(x) => x.poll_seek(cx, pos),
274
            }
275
0
        }
276
    }
277
278
    impl<A, B> AsyncBufRead for Either<A, B>
279
    where
280
        A: AsyncBufRead,
281
        B: AsyncBufRead,
282
    {
283
0
        fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
284
0
            match self.project() {
285
0
                Either::Left(x) => x.poll_fill_buf(cx),
286
0
                Either::Right(x) => x.poll_fill_buf(cx),
287
            }
288
0
        }
289
290
0
        fn consume(self: Pin<&mut Self>, amt: usize) {
291
0
            match self.project() {
292
0
                Either::Left(x) => x.consume(amt),
293
0
                Either::Right(x) => x.consume(amt),
294
            }
295
0
        }
296
    }
297
}