1use std::future::Future;
2
3pub trait AsyncResultExt<T, E> {
21 fn async_map<U, F, Fut>(self, op: F) -> impl Future<Output = Result<U, E>>
37 where
38 F: FnOnce(T) -> Fut,
39 Fut: Future<Output = U>;
40
41 fn async_and_then<U, F, Fut>(self, op: F) -> impl Future<Output = Result<U, E>>
56 where
57 F: FnOnce(T) -> Fut,
58 Fut: Future<Output = Result<U, E>>;
59
60 fn async_map_or<U, F, Fut>(self, default: U, op: F) -> impl Future<Output = U>
65 where
66 F: FnOnce(T) -> Fut,
67 Fut: Future<Output = U>;
68
69 fn async_map_or_else<U, D, F, Fut, DefFut>(self, default: D, op: F) -> impl Future<Output = U>
74 where
75 D: FnOnce(E) -> DefFut,
76 F: FnOnce(T) -> Fut,
77 DefFut: Future<Output = U>,
78 Fut: Future<Output = U>;
79
80 fn async_map_err<F, Fut, O>(self, op: F) -> impl Future<Output = Result<T, O>>
84 where
85 F: FnOnce(E) -> Fut,
86 Fut: Future<Output = O>;
87
88 fn async_inspect<F, Fut>(self, op: F) -> impl Future<Output = Self>
92 where
93 F: FnOnce(&T) -> Fut,
94 Fut: Future<Output = ()>;
95
96 fn async_inspect_err<F, Fut>(self, op: F) -> impl Future<Output = Self>
100 where
101 F: FnOnce(&E) -> Fut,
102 Fut: Future<Output = ()>;
103}
104
105impl<T, E> AsyncResultExt<T, E> for Result<T, E> {
106 async fn async_map<U, F, Fut>(self, op: F) -> Result<U, E>
107 where
108 F: FnOnce(T) -> Fut,
109 Fut: Future<Output = U>,
110 {
111 match self {
112 Ok(value) => Ok(op(value).await),
113 Err(err) => Err(err),
114 }
115 }
116
117 async fn async_and_then<U, F, Fut>(self, op: F) -> Result<U, E>
118 where
119 F: FnOnce(T) -> Fut,
120 Fut: Future<Output = Result<U, E>>,
121 {
122 match self {
123 Ok(value) => op(value).await,
124 Err(err) => Err(err),
125 }
126 }
127
128 async fn async_map_or<U, F, Fut>(self, default: U, op: F) -> U
129 where
130 F: FnOnce(T) -> Fut,
131 Fut: Future<Output = U>,
132 {
133 match self {
134 Ok(value) => op(value).await,
135 Err(_) => default,
136 }
137 }
138 async fn async_map_or_else<U, D, F, Fut, DefFut>(self, default: D, op: F) -> U
139 where
140 D: FnOnce(E) -> DefFut,
141 F: FnOnce(T) -> Fut,
142 DefFut: Future<Output = U>,
143 Fut: Future<Output = U>,
144 {
145 match self {
146 Ok(value) => op(value).await,
147 Err(err) => default(err).await,
148 }
149 }
150
151 async fn async_map_err<F, Fut, O>(self, op: F) -> Result<T, O>
152 where
153 F: FnOnce(E) -> Fut,
154 Fut: Future<Output = O>,
155 {
156 match self {
157 Ok(value) => Ok(value),
158 Err(err) => Err(op(err).await),
159 }
160 }
161
162 async fn async_inspect<F, Fut>(self, op: F) -> Self
163 where
164 F: FnOnce(&T) -> Fut,
165 Fut: Future<Output = ()>,
166 {
167 if let Ok(ref value) = self {
168 op(value).await;
169 }
170 self
171 }
172
173 async fn async_inspect_err<F, Fut>(self, op: F) -> Self
174 where
175 F: FnOnce(&E) -> Fut,
176 Fut: Future<Output = ()>,
177 {
178 if let Err(ref err) = self {
179 op(err).await;
180 }
181 self
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[tokio::test]
190 async fn test_async_map() {
191 let r: Result<i32, &str> = Ok(2);
192 let res = r.async_map(|v| async move { v * 3 }).await;
193 assert_eq!(res, Ok(6));
194
195 let r: Result<i32, &str> = Err("error");
196 let res = r.async_map(|v| async move { v * 3 }).await;
197 assert_eq!(res, Err("error"));
198 }
199
200 #[tokio::test]
201 async fn test_async_and_then() {
202 let r: Result<i32, &str> = Ok(2);
203 let res = r.async_and_then(|v| async move { Ok(v * 5) }).await;
204 assert_eq!(res, Ok(10));
205
206 let r: Result<i32, &str> = Err("fail");
207 let res = r.async_and_then(|v| async move { Ok(v * 5) }).await;
208 assert_eq!(res, Err("fail"));
209 }
210
211 #[tokio::test]
212 async fn test_async_map_or() {
213 let r: Result<i32, &str> = Ok(2);
214 let res = r.async_map_or(100, |v| async move { v * 4 }).await;
215 assert_eq!(res, 8);
216
217 let r: Result<i32, &str> = Err("fail");
218 let res = r.async_map_or(100, |v| async move { v * 4 }).await;
219 assert_eq!(res, 100);
220 }
221
222 #[tokio::test]
223 async fn test_async_map_err() {
224 let r: Result<i32, &str> = Ok(10);
225 let res = r.async_map_err(|e| async move { e.len() }).await;
226 assert_eq!(res, Ok(10));
227
228 let r: Result<i32, &str> = Err("fail");
229 let res = r.async_map_err(|e| async move { e.len() }).await;
230 assert_eq!(res, Err(4));
231 }
232
233 #[tokio::test]
234 async fn test_async_inspect_err() {
235 let r: Result<i32, &str> = Err("oops");
236 let mut seen = "";
237 let res = r
238 .async_inspect_err(|e| async {
239 seen = e;
240 })
241 .await;
242 assert_eq!(res, Err("oops"));
243 assert_eq!(seen, "oops");
244
245 let r: Result<i32, &str> = Ok(10);
246 let res = r
247 .async_inspect_err(|e| async {
248 seen = e;
249 })
250 .await;
251 assert_eq!(res, Ok(10));
252 }
253
254 #[tokio::test]
255 async fn test_async_map_or_else() {
256 let r: Result<i32, &str> = Ok(3);
257 let res = r
258 .async_map_or_else(|e| async move { e.len() as i32 }, |v| async move { v * 2 })
259 .await;
260 assert_eq!(res, 6);
261
262 let r: Result<i32, &str> = Err("error");
263 let res = r
264 .async_map_or_else(|e| async move { e.len() as i32 }, |v| async move { v * 2 })
265 .await;
266 assert_eq!(res, 5);
267 }
268}