Skip to main content

scc/
exit_guard.rs

1//! This module implements a simplified but safe version of
2//! [`scopeguard`](https://crates.io/crates/scopeguard).
3
4use std::mem::{ManuallyDrop, forget};
5use std::ops::{Deref, DerefMut};
6
7/// [`ExitGuard`] captures the environment and invokes a defined closure at the end of the scope.
8pub(crate) struct ExitGuard<T, F: FnOnce(T)> {
9    drop_callback: ManuallyDrop<(T, F)>,
10}
11
12impl<T, F: FnOnce(T)> ExitGuard<T, F> {
13    /// Creates a new [`ExitGuard`] with the specified variables captured.
14    #[inline]
15    pub(crate) const fn new(captured: T, drop_callback: F) -> Self {
16        Self {
17            drop_callback: ManuallyDrop::new((captured, drop_callback)),
18        }
19    }
20
21    /// Forgets the [`ExitGuard`] without invoking the drop callback.
22    #[inline]
23    pub(crate) fn forget(mut self) {
24        unsafe {
25            ManuallyDrop::drop(&mut self.drop_callback);
26        }
27        forget(self);
28    }
29}
30
31impl<T, F: FnOnce(T)> Drop for ExitGuard<T, F> {
32    #[inline]
33    fn drop(&mut self) {
34        let (c, f) = unsafe { ManuallyDrop::take(&mut self.drop_callback) };
35        f(c);
36    }
37}
38
39impl<T, F: FnOnce(T)> Deref for ExitGuard<T, F> {
40    type Target = T;
41
42    #[inline]
43    fn deref(&self) -> &Self::Target {
44        &self.drop_callback.0
45    }
46}
47
48impl<T, F: FnOnce(T)> DerefMut for ExitGuard<T, F> {
49    #[inline]
50    fn deref_mut(&mut self) -> &mut Self::Target {
51        &mut self.drop_callback.0
52    }
53}