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}