Skip to content

Commit fb27ffc

Browse files
authored
add future::Either type to utils (#305)
1 parent b068ea1 commit fb27ffc

File tree

8 files changed

+104
-7
lines changed

8 files changed

+104
-7
lines changed

actix-tracing/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ path = "src/lib.rs"
1717

1818
[dependencies]
1919
actix-service = "2.0.0-beta.5"
20+
actix-utils = "3.0.0-beta.3"
2021

21-
futures-util = { version = "0.3.7", default-features = false }
2222
tracing = "0.1"
2323
tracing-futures = "0.2"
2424

actix-tracing/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use core::marker::PhantomData;
99
use actix_service::{
1010
apply, ApplyTransform, IntoServiceFactory, Service, ServiceFactory, Transform,
1111
};
12-
use futures_util::future::{ok, Either, Ready};
12+
use actix_utils::future::{ok, Either, Ready};
1313
use tracing_futures::{Instrument, Instrumented};
1414

1515
/// A `Service` implementation that automatically enters/exits tracing spans
@@ -48,9 +48,9 @@ where
4848
.clone()
4949
.map(|span| tracing::span!(parent: &span, tracing::Level::INFO, "future"))
5050
{
51-
Either::Right(fut.instrument(span))
51+
Either::right(fut.instrument(span))
5252
} else {
53-
Either::Left(fut)
53+
Either::left(fut)
5454
}
5555
}
5656
}

actix-utils/CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Changes
22

33
## Unreleased - 2021-xx-xx
4+
* Add `future::Either` type. [#305]
5+
6+
[#305]: https://github.com/actix/actix-net/pull/305
47

58

69
## 3.0.0-beta.3 - 2021-04-01

actix-utils/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ name = "actix_utils"
1717
path = "src/lib.rs"
1818

1919
[dependencies]
20+
pin-project-lite = "0.2"
2021
local-waker = "0.1"
2122

2223
[dev-dependencies]

actix-utils/src/future/either.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//! A symmetric either future.
2+
3+
use core::{
4+
future::Future,
5+
pin::Pin,
6+
task::{Context, Poll},
7+
};
8+
9+
use pin_project_lite::pin_project;
10+
11+
pin_project! {
12+
/// Combines two different futures that have the same output type.
13+
///
14+
/// Construct variants with [`Either::left`] and [`Either::right`].
15+
///
16+
/// # Examples
17+
/// ```
18+
/// use actix_utils::future::{ready, Ready, Either};
19+
///
20+
/// # async fn run() {
21+
/// let res = Either::<_, Ready<usize>>::left(ready(42));
22+
/// assert_eq!(res.await, 42);
23+
///
24+
/// let res = Either::<Ready<usize>, _>::right(ready(43));
25+
/// assert_eq!(res.await, 43);
26+
/// # }
27+
/// ```
28+
#[project = EitherProj]
29+
#[derive(Debug, Clone)]
30+
pub enum Either<L, R> {
31+
/// A value of type `L`.
32+
#[allow(missing_docs)]
33+
Left { #[pin] value: L },
34+
35+
/// A value of type `R`.
36+
#[allow(missing_docs)]
37+
Right { #[pin] value: R },
38+
}
39+
}
40+
41+
impl<L, R> Either<L, R> {
42+
/// Creates new `Either` using left variant.
43+
pub fn left(value: L) -> Either<L, R> {
44+
Either::Left { value }
45+
}
46+
47+
/// Creates new `Either` using right variant.
48+
pub fn right(value: R) -> Either<L, R> {
49+
Either::Right { value }
50+
}
51+
}
52+
53+
impl<T> Either<T, T> {
54+
/// Unwraps into inner value when left and right have a common type.
55+
pub fn into_inner(self) -> T {
56+
match self {
57+
Either::Left { value } => value,
58+
Either::Right { value } => value,
59+
}
60+
}
61+
}
62+
63+
impl<L, R> Future for Either<L, R>
64+
where
65+
L: Future,
66+
R: Future<Output = L::Output>,
67+
{
68+
type Output = L::Output;
69+
70+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
71+
match self.project() {
72+
EitherProj::Left { value } => value.poll(cx),
73+
EitherProj::Right { value } => value.poll(cx),
74+
}
75+
}
76+
}
77+
78+
#[cfg(test)]
79+
mod tests {
80+
use super::*;
81+
use crate::future::{ready, Ready};
82+
83+
#[actix_rt::test]
84+
async fn test_either() {
85+
let res = Either::<_, Ready<usize>>::left(ready(42));
86+
assert_eq!(res.await, 42);
87+
88+
let res = Either::<Ready<usize>, _>::right(ready(43));
89+
assert_eq!(res.await, 43);
90+
}
91+
}

actix-utils/src/future/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! Asynchronous values.
22
3+
mod either;
34
mod poll_fn;
45
mod ready;
56

7+
pub use self::either::Either;
68
pub use self::poll_fn::{poll_fn, PollFn};
79
pub use self::ready::{err, ok, ready, Ready};

actix-utils/src/future/poll_fn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use core::{
77
task::{Context, Poll},
88
};
99

10-
/// Create a future driven by the provided function that receives a task context.
10+
/// Creates a future driven by the provided function that receives a task context.
1111
pub fn poll_fn<F, T>(f: F) -> PollFn<F>
1212
where
1313
F: FnMut(&mut Context<'_>) -> Poll<T>,

actix-utils/src/future/ready.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub fn ready<T>(val: T) -> Ready<T> {
6969
Ready { val: Some(val) }
7070
}
7171

72-
/// Create a future that is immediately ready with a success value.
72+
/// Creates a future that is immediately ready with a success value.
7373
///
7474
/// # Examples
7575
/// ```no_run
@@ -84,7 +84,7 @@ pub fn ok<T, E>(val: T) -> Ready<Result<T, E>> {
8484
Ready { val: Some(Ok(val)) }
8585
}
8686

87-
/// Create a future that is immediately ready with an error value.
87+
/// Creates a future that is immediately ready with an error value.
8888
///
8989
/// # Examples
9090
/// ```no_run

0 commit comments

Comments
 (0)