Skip to content

Commit 522d3bd

Browse files
committed
convenience Future ext methods: meanwhile and pend_after
1 parent 7d02397 commit 522d3bd

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

async_ui_web/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@ pub mod event_traits {
4343

4444
pub mod shortcut_traits {
4545
/*!
46-
Convenience traits. Includes traits for manipulating element classes and rendering str.
46+
Traits provided for convenience.
4747
*/
4848
pub use super::shortcuts::{ShortcutClassList, ShortcutClassListBuilder, ShortcutRenderStr};
49+
pub use async_ui_web_core::combinators::UiFutureExt;
4950
}
5051

5152
pub mod prelude_traits {
5253
/*!
53-
Includes traits from [event_traits][super::event_traits]
54+
Includes all traits from [event_traits][super::event_traits]
5455
and [shortcut_traits][super::shortcut_traits].
5556
```
5657
use async_ui_web::prelude_traits::*;
@@ -59,6 +60,7 @@ pub mod prelude_traits {
5960
pub use super::shortcuts::{
6061
ShortcutClassList as _, ShortcutClassListBuilder as _, ShortcutRenderStr as _,
6162
};
63+
pub use async_ui_web_core::combinators::UiFutureExt as _;
6264
pub use async_ui_web_html::events::{
6365
EmitElementEvent as _, EmitEvent as _, EmitHtmlElementEvent as _,
6466
};
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use std::{future::Future, marker::PhantomData};
2+
3+
/// Provides Future extension methods useful for writing UI.
4+
///
5+
/// Implemented for every `Future` type.
6+
pub trait UiFutureExt: Future + Sized {
7+
/// Turn the given future into one that never finishes.
8+
///
9+
/// You can specify the output type of the output future to be anything,
10+
/// because the future will never produce output.
11+
///
12+
/// ```rust
13+
/// # async fn my_async_fn() {}
14+
/// use async_ui_web_core::combinators::UiFutureExt;
15+
/// let fut = my_async_fn().pend_after::<std::convert::Infallible>();
16+
/// fut.await; // will never finish
17+
/// ```
18+
///
19+
/// `f.pend_after()` is equivalent to
20+
/// ```rust
21+
/// # let f = async {};
22+
/// async {
23+
/// f.await;
24+
/// std::future::pending()
25+
/// }
26+
/// ```
27+
fn pend_after<T>(self) -> PendAfter<Self, T> {
28+
PendAfter {
29+
future: Some(self),
30+
_phantom: PhantomData,
31+
}
32+
}
33+
/// Run some Future while this one is running.
34+
///
35+
/// `f.meanwhile(g)` is equivalent to
36+
/// ```rust
37+
/// # let (f, g) = (async {}, async{});
38+
/// # use async_ui_web_core::combinators::{UiFutureExt, race};
39+
/// race((
40+
/// f,
41+
/// g.pend_after()
42+
/// ))
43+
/// ```
44+
fn meanwhile<F: Future>(
45+
self,
46+
effect: F,
47+
) -> <(Self, PendAfter<F, Self::Output>) as super::race::Race>::Future {
48+
use super::race::Race;
49+
(self, effect.pend_after()).race()
50+
}
51+
}
52+
53+
impl<F: Future> UiFutureExt for F {}
54+
55+
#[pin_project::pin_project]
56+
pub struct PendAfter<F: Future, T> {
57+
#[pin]
58+
future: Option<F>,
59+
_phantom: PhantomData<T>,
60+
}
61+
62+
impl<F: Future, T> Future for PendAfter<F, T> {
63+
type Output = T;
64+
65+
fn poll(
66+
self: std::pin::Pin<&mut Self>,
67+
cx: &mut std::task::Context<'_>,
68+
) -> std::task::Poll<Self::Output> {
69+
let mut this = self.project();
70+
if let Some(fut) = this.future.as_mut().as_pin_mut() {
71+
if fut.poll(cx).is_ready() {
72+
this.future.set(None);
73+
}
74+
}
75+
std::task::Poll::Pending
76+
}
77+
}

async_ui_web_core/src/combinators/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
mod common;
2+
mod extras;
23
mod join;
34
mod race;
45
mod race_ok;
56
mod try_join;
67
mod utils;
78

9+
pub use extras::UiFutureExt;
10+
811
/// Wait for multiple futures to complete.
912
///
1013
/// Join takes in many "subfutures" and return a single Future.

0 commit comments

Comments
 (0)