Skip to main content

tuwunel_core/utils/
defer.rs

1//! Scope-exit guards for cleanup and temporary state changes.
2//!
3//! The macros create local drop guards that run cleanup as control leaves the
4//! surrounding scope. They cover arbitrary deferred actions and restoration of
5//! a replaced value.
6
7/// Runs an action when the surrounding scope exits.
8///
9/// A local drop guard executes the action on normal return, early return, or
10/// unwinding. Multiple guards in one scope run in reverse declaration order.
11#[macro_export]
12macro_rules! defer {
13	($body:block) => {
14		struct _Defer_<F: FnMut()> {
15			closure: F,
16		}
17
18		impl<F: FnMut()> Drop for _Defer_<F> {
19			fn drop(&mut self) { (self.closure)(); }
20		}
21
22		let _defer_ = _Defer_ { closure: || $body };
23	};
24
25	($body:expr_2021) => {
26		$crate::defer! {{ $body }}
27	};
28}
29
30/// Temporarily replaces a value and restores the previous value at scope exit.
31///
32/// The first argument is a mutable-reference identifier, and the second becomes
33/// its temporary value. A deferred drop guard performs restoration on normal
34/// return, early return, or unwinding.
35#[macro_export]
36macro_rules! scope_restore {
37	($val:ident, $ours:expr_2021) => {
38		let theirs = $crate::utils::exchange($val, $ours);
39		$crate::defer! {{ *$val = theirs; }};
40	};
41}