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}