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 fn async_is_ok_and<F, Fut>(self, op: F) -> impl Future<Output = bool>
128 where
129 F: FnOnce(T) -> Fut,
130 Fut: Future<Output = bool>;
131
132 fn async_is_err_and<F, Fut>(self, op: F) -> impl Future<Output = bool>
156 where
157 F: FnOnce(E) -> Fut,
158 Fut: Future<Output = bool>;
159}
160
161impl<T, E> AsyncResultExt<T, E> for Result<T, E> {
162 async fn async_map<U, F, Fut>(self, op: F) -> Result<U, E>
163 where
164 F: FnOnce(T) -> Fut,
165 Fut: Future<Output = U>,
166 {
167 match self {
168 Ok(value) => Ok(op(value).await),
169 Err(err) => Err(err),
170 }
171 }
172
173 async fn async_and_then<U, F, Fut>(self, op: F) -> Result<U, E>
174 where
175 F: FnOnce(T) -> Fut,
176 Fut: Future<Output = Result<U, E>>,
177 {
178 match self {
179 Ok(value) => op(value).await,
180 Err(err) => Err(err),
181 }
182 }
183
184 async fn async_map_or<U, F, Fut>(self, default: U, op: F) -> U
185 where
186 F: FnOnce(T) -> Fut,
187 Fut: Future<Output = U>,
188 {
189 match self {
190 Ok(value) => op(value).await,
191 Err(_) => default,
192 }
193 }
194 async fn async_map_or_else<U, D, F, Fut, DefFut>(self, default: D, op: F) -> U
195 where
196 D: FnOnce(E) -> DefFut,
197 F: FnOnce(T) -> Fut,
198 DefFut: Future<Output = U>,
199 Fut: Future<Output = U>,
200 {
201 match self {
202 Ok(value) => op(value).await,
203 Err(err) => default(err).await,
204 }
205 }
206
207 async fn async_map_err<F, Fut, O>(self, op: F) -> Result<T, O>
208 where
209 F: FnOnce(E) -> Fut,
210 Fut: Future<Output = O>,
211 {
212 match self {
213 Ok(value) => Ok(value),
214 Err(err) => Err(op(err).await),
215 }
216 }
217
218 async fn async_inspect<F, Fut>(self, op: F) -> Self
219 where
220 F: FnOnce(&T) -> Fut,
221 Fut: Future<Output = ()>,
222 {
223 if let Ok(ref value) = self {
224 op(value).await;
225 }
226 self
227 }
228
229 async fn async_inspect_err<F, Fut>(self, op: F) -> Self
230 where
231 F: FnOnce(&E) -> Fut,
232 Fut: Future<Output = ()>,
233 {
234 if let Err(ref err) = self {
235 op(err).await;
236 }
237 self
238 }
239
240 async fn async_is_ok_and<F, Fut>(self, op: F) -> bool
241 where
242 F: FnOnce(T) -> Fut,
243 Fut: Future<Output = bool>,
244 {
245 {
246 match self {
247 Err(_) => false,
248 Ok(v) => op(v).await,
249 }
250 }
251 }
252
253 async fn async_is_err_and<F, Fut>(self, op: F) -> bool
254 where
255 F: FnOnce(E) -> Fut,
256 Fut: Future<Output = bool>,
257 {
258 {
259 match self {
260 Ok(_) => false,
261 Err(e) => op(e).await,
262 }
263 }
264 }
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270
271 #[tokio::test]
272 async fn test_async_map() {
273 let r: Result<i32, &str> = Ok(2);
274 let res = r.async_map(|v| async move { v * 3 }).await;
275 assert_eq!(res, Ok(6));
276
277 let r: Result<i32, &str> = Err("error");
278 let res = r.async_map(|v| async move { v * 3 }).await;
279 assert_eq!(res, Err("error"));
280 }
281
282 #[tokio::test]
283 async fn test_async_and_then() {
284 let r: Result<i32, &str> = Ok(2);
285 let res = r.async_and_then(|v| async move { Ok(v * 5) }).await;
286 assert_eq!(res, Ok(10));
287
288 let r: Result<i32, &str> = Err("fail");
289 let res = r.async_and_then(|v| async move { Ok(v * 5) }).await;
290 assert_eq!(res, Err("fail"));
291 }
292
293 #[tokio::test]
294 async fn test_async_map_or() {
295 let r: Result<i32, &str> = Ok(2);
296 let res = r.async_map_or(100, |v| async move { v * 4 }).await;
297 assert_eq!(res, 8);
298
299 let r: Result<i32, &str> = Err("fail");
300 let res = r.async_map_or(100, |v| async move { v * 4 }).await;
301 assert_eq!(res, 100);
302 }
303
304 #[tokio::test]
305 async fn test_async_map_err() {
306 let r: Result<i32, &str> = Ok(10);
307 let res = r.async_map_err(|e| async move { e.len() }).await;
308 assert_eq!(res, Ok(10));
309
310 let r: Result<i32, &str> = Err("fail");
311 let res = r.async_map_err(|e| async move { e.len() }).await;
312 assert_eq!(res, Err(4));
313 }
314
315 #[tokio::test]
316 async fn test_async_inspect_err() {
317 let r: Result<i32, &str> = Err("oops");
318 let mut seen = "";
319 let res = r
320 .async_inspect_err(|e| async {
321 seen = e;
322 })
323 .await;
324 assert_eq!(res, Err("oops"));
325 assert_eq!(seen, "oops");
326
327 let r: Result<i32, &str> = Ok(10);
328 let res = r
329 .async_inspect_err(|e| async {
330 seen = e;
331 })
332 .await;
333 assert_eq!(res, Ok(10));
334 }
335
336 #[tokio::test]
337 async fn test_async_map_or_else() {
338 let r: Result<i32, &str> = Ok(3);
339 let res = r
340 .async_map_or_else(|e| async move { e.len() as i32 }, |v| async move { v * 2 })
341 .await;
342 assert_eq!(res, 6);
343
344 let r: Result<i32, &str> = Err("error");
345 let res = r
346 .async_map_or_else(|e| async move { e.len() as i32 }, |v| async move { v * 2 })
347 .await;
348 assert_eq!(res, 5);
349 }
350
351 #[tokio::test]
352 async fn async_is_ok_and() {
353 let r: Result<i32, &str> = Ok(5);
354 let res = r.async_is_ok_and(|_| async move { false }).await;
355 assert!(!res);
356
357 let r: Result<i32, &str> = Err("error");
358 let res = r.async_is_ok_and(|_| async move { false }).await;
359 assert!(!res);
360 }
361
362 #[tokio::test]
363 async fn is_err_and() {
364 let r: Result<i32, &str> = Ok(5);
365 let res = r.async_is_err_and(|_| async move { true }).await;
366 assert!(!res);
367
368 let r: Result<i32, &str> = Err("error");
369 let res = r.async_is_err_and(|_| async move { false }).await;
370 assert!(!res);
371 }
372}