future_result/lib.rs
1//! An ideomatic way of mapping a [Result](std::result::Result) to a [Future](core::future::Future)
2//! of [Result](std::result::Result).
3//!
4//! # Example usage
5//!
6//! ```
7//! use future_result::FutureResult;
8//!
9//! async fn add_1(x: u32) -> u32 {
10//! x + 1
11//! }
12//!
13//! fn main() {
14//! let fut = async {
15//! let ok: Result<u32, ()> = Ok(41);
16//! let ok = ok.then_map(add_1).await;
17//!
18//! assert_eq!(Ok(42), ok);
19//!
20//! // ...
21//!
22//! let err: Result<(), u32> = Err(9);
23//! let err = err.then_map_err(add_1).await;
24//!
25//! assert_eq!(Err(10), err);
26//! };
27//!
28//! futures::executor::block_on(fut);
29//! }
30//! ```
31
32use async_trait::async_trait;
33use core::future::Future;
34
35/// A [Result](std::result::Result), which can be transformed into a
36/// [Future](core::future::Future) of [Result](std::result::Result)
37#[async_trait(?Send)]
38pub trait FutureResult {
39 /// The success value of the `Result`
40 type Ok;
41
42 /// The error value of the `Result`
43 type Err;
44
45 /// Maps a `Result<T, E>` to a `Future<Output = Result<U, E>` by applying
46 /// a function to the contained [`Ok`] value.
47 /// [`Err`] is left untouched.
48 ///
49 /// # Examples
50 ///
51 /// ```
52 /// # use future_result::FutureResult;
53 /// let ok: Result<u8, ()> = Ok(1);
54 /// let err: Result<bool, ()> = Err(());
55 ///
56 /// futures::executor::block_on(async move {
57 /// let ok = ok.then_map(|x| async move { x + 6 }).await;
58 /// assert_eq!(Ok(7), ok);
59 ///
60 /// let err = err.then_map(|b| async move { !b }).await;
61 /// assert_eq!(Err(()), err);
62 /// });
63 /// ```
64 async fn then_map<U, F, Fut>(self, f: F) -> Result<U, Self::Err>
65 where
66 F: FnOnce(Self::Ok) -> Fut,
67 Fut: Future<Output = U>;
68
69 /// Maps a `Result<T, E>` to a `Future<Output = Result<T, U>` by applying
70 /// a function to the contained [`Err`] value.
71 /// [`Ok`] is left untouched.
72 ///
73 /// # Examples
74 ///
75 /// ```
76 /// # use future_result::FutureResult;
77 /// let ok: Result<(), bool> = Ok(());
78 /// let err: Result<(), u8> = Err(8);
79 ///
80 /// futures::executor::block_on(async move {
81 /// let err = err.then_map_err(|x| async move { x - 3 }).await;
82 /// assert_eq!(Err(5), err);
83 ///
84 /// let ok = ok.then_map_err(|b| async move { !b }).await;
85 /// assert_eq!(Ok(()), ok);
86 /// });
87 /// ```
88 async fn then_map_err<U, F, Fut>(self, f: F) -> Result<Self::Ok, U>
89 where
90 F: FnOnce(Self::Err) -> Fut,
91 Fut: Future<Output = U>;
92}
93
94#[async_trait(?Send)]
95impl<T: Sync, E: Sync> FutureResult for Result<T, E> {
96 type Ok = T;
97 type Err = E;
98
99 async fn then_map<U, F, Fut>(self, f: F) -> Result<U, E>
100 where
101 Self: Sized,
102 F: FnOnce(T) -> Fut,
103 Fut: Future<Output = U>,
104 {
105 match self {
106 Ok(x) => Ok(f(x).await),
107 Err(e) => Err(e),
108 }
109 }
110
111 async fn then_map_err<U, F, Fut>(self, f: F) -> Result<T, U>
112 where
113 Self: Sized,
114 F: FnOnce(E) -> Fut,
115 Fut: Future<Output = U>,
116 {
117 match self {
118 Ok(x) => Ok(x),
119 Err(e) => Err(f(e).await),
120 }
121 }
122}