1
// Extracted from the scopeguard crate
2
use core::{
3
    mem,
4
    ops::{Deref, DerefMut},
5
    ptr,
6
};
7

            
8
pub struct ScopeGuard<T, F>
9
where
10
    F: FnMut(&mut T),
11
{
12
    dropfn: F,
13
    value: T,
14
}
15

            
16
#[inline]
17
pub fn guard<T, F>(value: T, dropfn: F) -> ScopeGuard<T, F>
18
where
19
    F: FnMut(&mut T),
20
{
21
    ScopeGuard { dropfn, value }
22
}
23

            
24
impl<T, F> ScopeGuard<T, F>
25
where
26
    F: FnMut(&mut T),
27
{
28
    #[inline]
29
    pub fn into_inner(guard: Self) -> T {
30
        // Cannot move out of Drop-implementing types, so
31
        // ptr::read the value and forget the guard.
32
        unsafe {
33
            let value = ptr::read(&guard.value);
34
            // read the closure so that it is dropped, and assign it to a local
35
            // variable to ensure that it is only dropped after the guard has
36
            // been forgotten. (In case the Drop impl of the closure, or that
37
            // of any consumed captured variable, panics).
38
            let _dropfn = ptr::read(&guard.dropfn);
39
            mem::forget(guard);
40
            value
41
        }
42
    }
43
}
44

            
45
impl<T, F> Deref for ScopeGuard<T, F>
46
where
47
    F: FnMut(&mut T),
48
{
49
    type Target = T;
50
    #[inline]
51
    fn deref(&self) -> &T {
52
        &self.value
53
    }
54
}
55

            
56
impl<T, F> DerefMut for ScopeGuard<T, F>
57
where
58
    F: FnMut(&mut T),
59
{
60
    #[inline]
61
    fn deref_mut(&mut self) -> &mut T {
62
        &mut self.value
63
    }
64
}
65

            
66
impl<T, F> Drop for ScopeGuard<T, F>
67
where
68
    F: FnMut(&mut T),
69
{
70
    #[inline]
71
    fn drop(&mut self) {
72
        (self.dropfn)(&mut self.value);
73
    }
74
}