Skip to content

Commit 634330b

Browse files
committed
defer macro
1 parent 840b045 commit 634330b

2 files changed

Lines changed: 79 additions & 12 deletions

File tree

src/errors.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,3 @@ impl AccessError {
9999
}
100100
}
101101
}
102-
103-
/// Try run a potentially async block of arguments with result type [`AccessError`],
104-
/// always discard the result and does not log the error.
105-
#[macro_export]
106-
macro_rules! attempt {
107-
($($tt:tt)*) => {
108-
let _: $crate::AccessResult<()> = async {
109-
let _ = {$($tt)*};
110-
Ok(())
111-
}.await;
112-
};
113-
}

src/lib.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,85 @@ impl<S: States> Command for StateScopedSpawnFn<S> {
556556
}
557557
}
558558

559+
#[doc(hidden)]
560+
#[must_use = "Defer must not be dropped immediately."]
561+
pub struct Defer<F: FnOnce() -> AccessResult>(pub Option<F>);
562+
563+
impl<F: FnOnce() -> AccessResult> Drop for Defer<F> {
564+
fn drop(&mut self) {
565+
if in_async_context() {
566+
let _ = (self.0.take().unwrap())();
567+
}
568+
}
569+
}
570+
571+
/// Defer a set of statements that automatically triggers when the future is either completed
572+
/// or dropped (i.e. via select!)
573+
///
574+
/// # Returns
575+
///
576+
/// Returns a variable that triggers these statements on drop.
577+
///
578+
/// # Note
579+
///
580+
/// If the world is dropped, these statements will NOT be ran since `bevy_defer` functions
581+
/// will likely panic if the world is no longer available.
582+
///
583+
/// # Example
584+
///
585+
/// ```
586+
/// # use bevy_defer::{AccessResult, defer};
587+
/// # async fn dance(entity: i32) -> AccessResult { Ok(()) }
588+
/// # fn stop_dancing(entity: i32) -> AccessResult { Ok(()) }
589+
/// # async fn test() -> AccessResult {
590+
/// # let entity = 1;
591+
/// // Must be bound to a variable and not `_` so it lives until the end of the future.
592+
/// let _deferred = defer! {
593+
/// // stop dancing when the future is dropped
594+
/// stop_dancing(entity)?;
595+
/// };
596+
/// dance(entity).await?;
597+
/// # Ok(()) }
598+
/// ```
599+
#[macro_export]
600+
macro_rules! defer {
601+
($($tt: tt)*) => {
602+
$crate::Defer(Some(|| {
603+
let _ = {$($tt)*};
604+
Ok(())
605+
}))
606+
};
607+
}
608+
609+
/// Try run a potentially async block of arguments with result type [`AccessError`],
610+
/// always discard the result and does not log the error.
611+
///
612+
/// # Example
613+
///
614+
/// ```
615+
/// # use bevy_defer::{AccessResult, attempt};
616+
/// # async fn dance(entity: i32) -> AccessResult { Ok(()) }
617+
/// # async fn stop_dancing(entity: i32) -> AccessResult { Ok(()) }
618+
/// # async fn test() -> AccessResult {
619+
/// # let entity = 1;
620+
/// dance(entity).await?;
621+
/// // Must be bound to a variable and not `_` so it lives until the end of the future.
622+
/// attempt! {
623+
/// stop_dancing(entity).await?;
624+
/// };
625+
/// # Ok(()) }
626+
/// ```
627+
#[macro_export]
628+
macro_rules! attempt {
629+
($($tt:tt)*) => {
630+
let _: $crate::AccessResult<()> = async {
631+
let _ = {$($tt)*};
632+
Ok(())
633+
}.await;
634+
};
635+
}
636+
637+
559638
#[doc(hidden)]
560639
#[allow(unused)]
561640
#[macro_export]

0 commit comments

Comments
 (0)