drop_move/
drop_guard.rs

1use super::*;
2
3drop_move_wrap! {
4    /// Run a [`FnOnce`] function on drop.
5    #[derive(Clone)]
6    pub struct DropGuard<F: FnOnce()>(DropGuardInner {
7        func: F,
8    });
9}
10
11impl<F: FnOnce()> DropMove for DropGuardInner<F> {
12    fn drop_move(self_: DropHandle<Self>) {
13        (DropHandle::into_inner(self_).func)()
14    }
15}
16
17impl<F: FnOnce()> DropGuard<F> {
18    /// Construct from a [`FnOnce`] function.
19    pub fn new(f: F) -> Self {
20        DropGuardInner { func: f }.into()
21    }
22
23    /// Extract the function.
24    pub fn into_inner(self) -> F {
25        let inner = DropGuardInner::from(self);
26        inner.func
27    }
28}
29
30impl<F: FnOnce()> Deref for DropGuard<F> {
31    type Target = F;
32
33    fn deref(&self) -> &F {
34        &self.0.func
35    }
36}
37
38impl<F: FnOnce()> DerefMut for DropGuard<F> {
39    fn deref_mut(&mut self) -> &mut F {
40        &mut self.0.func
41    }
42}
43
44impl<F: FnOnce()> From<F> for DropGuard<F> {
45    fn from(f: F) -> Self {
46        DropGuard::new(f)
47    }
48}
49
50#[cfg(test)]
51mod test {
52    use super::*;
53
54    extern crate std;
55    use std::boxed::Box;
56
57    #[test]
58    fn test_drop() {
59        let mut x: u32 = 0;
60        let z: u32 = 0xdeadbeef;
61        let y = Box::<u32>::new(z);
62
63        assert!(x != z);
64        {
65            let x_ref = &mut x;
66            let f = move || *x_ref = *y;
67            let guard = DropGuard::new(f);
68
69            let f = guard.into_inner();
70            DropGuard::new(f);
71        }
72        assert_eq!(x, z);
73    }
74
75    #[test]
76    fn test_get() {
77        let mut x: u32 = 0;
78
79        {
80            let mut f = || x += 1;
81            f();
82
83            let mut guard = DropGuard::new(f);
84            guard.deref_mut()();
85        }
86
87        assert_eq!(x, 3);
88    }
89}