gearbox/rails/ext/future/mod.rs
1//! ## FutureOptional and FutureResult Documentation
2//!
3//! ### FutureOptional
4//!
5//! An extension trait for `Future`s that yield `Option<T>` that provides a variety of convenient adapters.
6//!
7//! #### `map`
8//!
9//! Map this future's optional output to a different type, returning a new future of the resulting type.
10//!
11//! This function is similar to the `Option::map` where it will change the type of the underlying future. This is useful to chain along a computation once a future has been resolved and if it is `Some`.
12//!
13//! ##### Example
14//!
15//! ```rust
16//! # futures::executor::block_on(async {
17//! use gearbox::rails::ext::future::FutureOptional;
18//!
19//! let future_opt = async { Some(1) };
20//! let res = future_opt.map(|t| async move { 5 });
21//! let final_res = res.await;
22//! assert_eq!(final_res, Some(5));
23//! # });
24//! ```
25//!
26//! #### `and_then`
27//!
28//! Chains this future with another future if the output is `Some`, returning a new future of the resulting type.
29//!
30//! This function is similar to the `Option::and_then` where it will chain another computation if the future resolves to `Some`.
31//!
32//! ##### Example
33//!
34//! ```rust
35//! # futures::executor::block_on(async {
36//! use gearbox::rails::ext::future::FutureOptional;
37//!
38//! let future_opt = async { Some(1) };
39//! let res = future_opt.and_then(|t| async move { Some(t + 1) });
40//! let final_res = res.await;
41//! assert_eq!(final_res, Some(2));
42//! # });
43//! ```
44//!
45//! #### `filter`
46//!
47//! Filters the output of this future, returning `None` if the predicate returns `false`.
48//!
49//! This function is similar to the `Option::filter` where it will return `None` if the predicate returns `false`.
50//!
51//! ##### Example
52//!
53//! ```rust
54//! # futures::executor::block_on(async {
55//! use gearbox::rails::ext::future::FutureOptional;
56//!
57//! let future_opt = async { Some(4) };
58//! let res = future_opt.filter(|x| *x > 2);
59//! let final_res = res.await;
60//! assert_eq!(final_res, Some(4));
61//! # });
62//! ```
63//!
64//! #### `or`
65//!
66//! Returns this future's output if it is `Some`, otherwise returns the provided fallback.
67//!
68//! This function is similar to the `Option::or` where it will return the provided fallback if the future resolves to `None`.
69//!
70//! ##### Example
71//!
72//! ```rust
73//! # futures::executor::block_on(async {
74//! use gearbox::rails::ext::future::FutureOptional;
75//!
76//! let future_opt = async { Some(4) };
77//! let res = future_opt.or(Some(10));
78//! let final_res = res.await;
79//! assert_eq!(final_res, Some(4));
80//!
81//! let future_opt = async { None };
82//! let res = future_opt.or(Some(10));
83//! let final_res = res.await;
84//! assert_eq!(final_res, Some(10));
85//! # });
86//! ```
87//!
88//! #### `or_else`
89//!
90//! Returns this future's output if it is `Some`, otherwise calls the provided fallback function.
91//!
92//! This function is similar to the `Option::or_else` where it will call the provided fallback function if the future resolves to `None`.
93//!
94//! ##### Example
95//!
96//! ```rust
97//! # futures::executor::block_on(async {
98//! use gearbox::rails::ext::future::FutureOptional;
99//!
100//! let future_opt = async { Some(4) };
101//! let res = future_opt.or_else(|| async { Some(10) });
102//! let final_res = res.await;
103//! assert_eq!(final_res, Some(4));
104//!
105//! let future_opt = async { None };
106//! let res = future_opt.or_else(|| async { Some(10) });
107//! let final_res = res.await;
108//! assert_eq!(final_res, Some(10));
109//! # });
110//! ```
111//!
112//! #### `unwrap_or`
113//!
114//! Returns this future's output if it is `Some`, otherwise returns the provided default.
115//!
116//! This function is similar to the `Option::unwrap_or` where it will return the provided default if the future resolves to `None`.
117//!
118//! ##### Example
119//!
120//! ```rust
121//! # futures::executor::block_on(async {
122//! use gearbox::rails::ext::future::FutureOptional;
123//!
124//! let future_opt = async { Some(4) };
125//! let res = future_opt.unwrap_or(10);
126//! let final_res = res.await;
127//! assert_eq!(final_res, 4);
128//!
129//! let future_opt = async { None };
130//! let res = future_opt.unwrap_or(10);
131//! let final_res = res.await;
132//! assert_eq!(final_res, 10);
133//! # });
134//! ```
135//!
136//! #### `unwrap_or_else`
137//!
138//! Returns this future's output if it is `Some`, otherwise calls the provided fallback function.
139//!
140//! This function is similar to the `Option::unwrap_or_else` where it will call the provided fallback function if the future resolves to `None`.
141//!
142//! ##### Example
143//!
144//! ```rust
145//! # futures::executor::block_on(async {
146//! use gearbox::rails::ext::future::FutureOptional;
147//!
148//! let future_opt = async { Some(4) };
149//! let res = future_opt.unwrap_or_else(|| async { 10 });
150//! let final_res = res.await;
151//! assert_eq!(final_res, 4);
152//!
153//! let future_opt = async { None };
154//! let res = future_opt.unwrap_or_else(|| async { 10 });
155//! let final_res = res.await;
156//! assert_eq!(final_res, 10);
157//! # });
158//! ```
159//!
160//! #### `merge`
161//!
162//! Merges this future with an optional value, producing a new future.
163//!
164//! This function takes an additional option and a function to combine the resolved value of the future and the option into a new future.
165//!
166//! ##### Example
167//!
168//! ```rust
169//! # futures::executor::block_on(async {
170//! use gearbox::rails::ext::future::FutureOptional;
171//!
172//! async fn func(x: u32, y: u32) -> Option<u32> {
173//! Some(x + y)
174//! }
175//!
176//! let x = async { Some(1) };
177//! let y = Some(2);
178//!
179//! let res = x.merge(y, |var_x, var_y| func(var_x, var_y));
180//! assert_eq!(res.await, Some(3));
181//! # });
182//! ```
183//!
184//! #### `merge2`
185//!
186//! Merges this future with two optional values, producing a new future.
187//!
188//! This function takes two additional options and a function to combine the resolved value of the future and the options into a new future.
189//!
190//! ##### Example
191//!
192//! ```rust
193//! # futures::executor::block_on(async {
194//! use gearbox::rails::ext::future::FutureOptional;
195//!
196//! async fn func(x: u32, y: u32, z: u32) -> Option<u32> {
197//! Some(x + y + z)
198//! }
199//!
200//! let x = async { Some(1) };
201//! let y = Some(2);
202//! let z = Some(3);
203//!
204//! let res = x.merge2(y, z, |var_x, var_y, var_z| func(var_x, var_y, var_z));
205//! assert_eq!(res.await, Some(6));
206//! # });
207//! ```
208//!
209//! #### `merge3`
210//!
211//! Merges this future with three optional values, producing a new future.
212//!
213//! This function takes three additional options and a function to combine the resolved value of the future and the options into a new future.
214//!
215//! ##### Example
216//!
217//! ```rust
218//! # futures::executor::block_on(async {
219//! use gearbox::rails::ext::future::FutureOptional;
220//!
221//! async fn func(x: u32, y: u32, z: u32, a: u32) -> Option<u32> {
222//! Some(x + y + z + a)
223//! }
224//!
225//! let x = async { Some(1) };
226//! let y = Some(2);
227//! let z = Some(3);
228//! let a = Some(4);
229//!
230//! let res = x.merge3(y, z, a, |var_x, var_y, var_z, var_a| func(var_x, var_y, var_z, var_a));
231//! assert_eq!(res.await, Some(10));
232//! # });
233//! ```
234//!
235//! #### `merge4`
236//!
237//! Merges this future with four optional values, producing a new future.
238//!
239//! This function takes four additional options and a function to combine the resolved value of the future and the options into a new future.
240//!
241//! ##### Example
242//!
243//! ```rust
244//! # futures::executor::block_on(async {
245//! use gearbox::rails::ext::future::FutureOptional;
246//!
247//! async fn func(x: u32, y: u32, z: u32, a: u32, b: u32) -> Option<u32> {
248//! Some(x + y + z + a + b)
249//! }
250//!
251//! let x = async { Some(1) };
252//! let y = Some(2);
253//! let z = Some(3);
254//! let a = Some(4);
255//! let b = Some(5);
256//!
257//! let res = x.merge4(y, z, a, b, |var_x, var_y, var_z, var_a, var_b| func(var_x, var_y, var_z, var_a, var_b));
258//! assert_eq!(res.await, Some(15));
259//! # });
260//! ```
261//!
262//! ### FutureResult
263//!
264//! An extension trait for `Future`s that yield `Result<T, E>` that provides a variety of convenient adapters.
265//!
266//! #### `map`
267//!
268//! Map this future's result output to a different type, returning a new future of the resulting type.
269//!
270//! This function is similar to the `Result::map` where it will change the type of the underlying future. This is useful to chain along a computation once a future has been resolved and if it is `Ok`.
271//!
272//! ##### Example
273//!
274//! ```rust
275//! # futures::executor::block_on(async {
276//! use gearbox::rails::ext::future::FutureResult;
277//!
278//! let future_res = async { Ok::<_, ()>(1) };
279//! let res = future_res.map(|t| async move { 5 });
280//! let final_res = res.await;
281//! assert_eq!(final_res, Ok(5));
282//! # });
283//! ```
284//!
285//! #### `map_or`
286//!
287//! Maps a `Result` by applying a function to the contained `Ok` value, or a default value if it is `Err`.
288//!
289//! This function is similar to the `Result::map_or`.
290//!
291//! ##### Example
292//!
293//! ```rust
294//! # futures::executor::block_on(async
295//!
296//! {
297//! use gearbox::rails::ext::future::FutureResult;
298//!
299//! let future_res = async { Ok::<_, ()>(1) };
300//! let res = future_res.map_or(10, |t| async move { t + 1 });
301//! let final_res = res.await;
302//! assert_eq!(final_res, 2);
303//!
304//! let future_res = async { Err::<i32, _>(()) };
305//! let res = future_res.map_or(10, |t| async move { t + 1 });
306//! let final_res = res.await;
307//! assert_eq!(final_res, 10);
308//! # });
309//! ```
310//!
311//! #### `map_err`
312//!
313//! Maps a `Result` by applying a function to the contained `Err` value.
314//!
315//! This function is similar to the `Result::map_err`.
316//!
317//! ##### Example
318//!
319//! ```rust
320//! # futures::executor::block_on(async {
321//! use gearbox::rails::ext::future::FutureResult;
322//!
323//! let future_res = async { Err::<u32, _>(1) };
324//! let res = future_res.map_err(|e| async move { e + 1 });
325//! let final_res = res.await;
326//! assert_eq!(final_res, Err(2));
327//! # });
328//! ```
329//!
330//! #### `and_then`
331//!
332//! Chains this future with another future if the output is `Ok`, returning a new future of the resulting type.
333//!
334//! This function is similar to the `Result::and_then` where it will chain another computation if the future resolves to `Ok`.
335//!
336//! ##### Example
337//!
338//! ```rust
339//! # futures::executor::block_on(async {
340//! use gearbox::rails::ext::future::FutureResult;
341//!
342//! let future_res = async { Ok::<_, ()>(1) };
343//! let res = future_res.and_then(|t| async move { Ok(t + 1) });
344//! let final_res = res.await;
345//! assert_eq!(final_res, Ok(2));
346//! # });
347//! ```
348//!
349//! #### `or_else`
350//!
351//! Returns this future's result if it is `Ok`, otherwise calls the provided fallback function.
352//!
353//! This function is similar to the `Result::or_else` where it will call the provided fallback function if the future resolves to `Err`.
354//!
355//! ##### Example
356//!
357//! ```rust
358//! # futures::executor::block_on(async {
359//! use gearbox::rails::ext::future::FutureResult;
360//!
361//! let future_res = async { Ok::<_, ()>(4) };
362//! let res = future_res.or_else(|_| async { Ok(10) });
363//! let final_res = res.await;
364//! assert_eq!(final_res, Ok(4));
365//!
366//! let future_res = async { Err::<i32, _>(()) };
367//! let res = future_res.or_else(|_| async { Ok(10) });
368//! let final_res = res.await;
369//! assert_eq!(final_res, Ok(10));
370//! # });
371//! ```
372//!
373//! #### `unwrap_or_else`
374//!
375//! Returns this future's result if it is `Ok`, otherwise calls the provided fallback function.
376//!
377//! This function is similar to the `Result::unwrap_or_else` where it will call the provided fallback function if the future resolves to `Err`.
378//!
379//! ##### Example
380//!
381//! ```rust
382//! # futures::executor::block_on(async {
383//! use gearbox::rails::ext::future::FutureResult;
384//!
385//! let future_res = async { Ok::<_, ()>(4) };
386//! let res = future_res.unwrap_or_else(|_| async { 10 });
387//! let final_res = res.await;
388//! assert_eq!(final_res, 4);
389//!
390//! let future_res = async { Err::<i32, _>(()) };
391//! let res = future_res.unwrap_or_else(|_| async { 10 });
392//! let final_res = res.await;
393//! assert_eq!(final_res, 10);
394//! # });
395//! ```
396//!
397//! #### `merge`
398//!
399//! Merges this future with a result value, producing a new future.
400//!
401//! This function takes an additional result and a function to combine the resolved value of the future and the result into a new future.
402//!
403//! ##### Example
404//!
405//! ```rust
406//! # futures::executor::block_on(async {
407//! use gearbox::rails::ext::future::FutureResult;
408//!
409//! async fn func(x: u32, y: u32) -> Result<u32, ()> {
410//! Ok(x + y)
411//! }
412//!
413//! let x = async { Ok::<_, ()>(1) };
414//! let y = Ok(2);
415//!
416//! let res = x.merge(y, |var_x, var_y| func(var_x, var_y));
417//! assert_eq!(res.await, Ok(3));
418//! # });
419//! ```
420//!
421//! #### `merge2`
422//!
423//! Merges this future with two result values, producing a new future.
424//!
425//! This function takes two additional results and a function to combine the resolved value of the future and the results into a new future.
426//!
427//! ##### Example
428//!
429//! ```rust
430//! # futures::executor::block_on(async {
431//! use gearbox::rails::ext::future::FutureResult;
432//!
433//! async fn func(x: u32, y: u32, z: u32) -> Result<u32, ()> {
434//! Ok(x + y + z)
435//! }
436//!
437//! let x = async { Ok::<_, ()>(1) };
438//! let y = Ok(2);
439//! let z = Ok(3);
440//!
441//! let res = x.merge2(y, z, |var_x, var_y, var_z| func(var_x, var_y, var_z));
442//! assert_eq!(res.await, Ok(6));
443//! # });
444//! ```
445//!
446//! #### `merge3`
447//!
448//! Merges this future with three result values, producing a new future.
449//!
450//! This function takes three additional results and a function to combine the resolved value of the future and the results into a new future.
451//!
452//! ##### Example
453//!
454//! ```rust
455//! # futures::executor::block_on(async {
456//! use gearbox::rails::ext::future::FutureResult;
457//!
458//! async fn func(x: u32, y: u32, z: u32, a: u32) -> Result<u32, ()> {
459//! Ok(x + y + z + a)
460//! }
461//!
462//! let x = async { Ok::<_, ()>(1) };
463//! let y = Ok(2);
464//! let z = Ok(3);
465//! let a = Ok(4);
466//!
467//! let res = x.merge3(y, z, a, |var_x, var_y, var_z, var_a| func(var_x, var_y, var_z, var_a));
468//! assert_eq!(res.await, Ok(10));
469//! # });
470//! ```
471//!
472//! #### `merge4`
473//!
474//! Merges this future with four result values, producing a new future.
475//!
476//! This function takes four additional results and a function to combine the resolved value of the future and the results into a new future.
477//!
478//! ##### Example
479//!
480//! ```rust
481//! # futures::executor::block_on(async {
482//! use gearbox::rails::ext::future::FutureResult;
483//!
484//! async fn func(x: u32, y: u32, z: u32, a: u32, b: u32) -> Result<u32, ()> {
485//! Ok(x + y + z + a + b)
486//! }
487//!
488//! let x = async { Ok::<_, ()>(1) };
489//! let y = Ok(2);
490//! let z = Ok(3);
491//! let a = Ok(4);
492//! let b = Ok(5);
493//!
494//! let res = x.merge4(y, z, a, b, |var_x, var_y, var_z, var_a, var_b| func(var_x, var_y, var_z, var_a, var_b));
495//! assert_eq!(res.await, Ok(15));
496//! # });
497//! ```
498
499pub mod ext;
500pub mod future_ext;
501
502pub(crate) mod private_utils;
503
504use alloc::boxed::Box;
505use core::{future::Future, pin::Pin};
506
507pub use future_ext::*;
508
509pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
510
511pub(crate) fn assert_future<T, F>(future: F) -> F
512where
513 F: Future<Output = T>,
514{
515 future
516}