mycelium_util/
deferred.rs

1//! Deferred closure execution (a.k.a. scope guards).
2//!
3//! See the [`Deferred`] type and the [`defer`] function for more information.
4
5/// Defers execution of a closure until a scope is exited.
6///
7/// As seen in "The Go Programming Language".
8#[must_use = "dropping a `Deferred` guard immediately executes \
9    the deferred function"]
10pub struct Deferred<F: FnOnce()>(Option<F>);
11
12impl<F: FnOnce()> Deferred<F> {
13    /// Defer execution of `f` until this scope is exited.
14    #[inline]
15    pub const fn new(f: F) -> Self {
16        Self(Some(f))
17    }
18
19    /// Cancel the deferred execution.of the closure passed to `defer`.
20    ///
21    /// Calling this method will prevent the closure from being executed when
22    /// this `Deferred` guard is dropped.
23    #[inline]
24    pub fn cancel(&mut self) {
25        self.0 = None;
26    }
27}
28
29impl<F: FnOnce()> Drop for Deferred<F> {
30    #[inline]
31    fn drop(&mut self) {
32        if let Some(f) = self.0.take() {
33            f()
34        }
35    }
36}
37
38impl<F: FnOnce()> core::fmt::Debug for Deferred<F> {
39    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
40        f.debug_tuple("Deferred")
41            .field(&format_args!("{}", core::any::type_name::<F>()))
42            .finish()
43    }
44}
45
46/// Defer execution of `f` until this scope is exited.
47///
48/// This is equivalent to calling `Deferred::new(f)`. See [`Deferred`] for more
49/// details.
50#[inline(always)]
51pub fn defer<F: FnOnce()>(f: F) -> Deferred<F> {
52    Deferred::new(f)
53}