Skip to main content

core_extensions/
on_drop.rs

1use crate::utils::take_manuallydrop;
2
3use std_::mem::ManuallyDrop;
4
5#[cfg(test)]
6mod tests;
7
8
9/// A wrapper type that runs a closure at the end of the scope.
10///
11/// This takes both a value and a closure(that takes the value as a parameter),
12/// allowing you to access the value before the closure runs.
13///
14/// # Example
15///
16/// ```rust
17/// use core_extensions::RunOnDrop;
18///
19/// fn main() { 
20///     let mut guard = RunOnDrop::new("Hello".to_string(), |string|{
21///         assert_eq!(string, "Hello, world!");
22///     });
23///
24///     assert_eq!(guard.get(), "Hello");
25///     
26///     guard.get_mut().push_str(", world!");
27/// }   
28///
29/// ```
30#[cfg_attr(feature = "docsrs", doc(cfg(feature = "on_drop")))]
31pub struct RunOnDrop<T, F>
32where
33    F: FnOnce(T),
34{
35    value: ManuallyDrop<T>,
36    function: ManuallyDrop<F>,
37}
38
39impl<T, F> RunOnDrop<T, F>
40where
41    F: FnOnce(T),
42{
43    /// Constructs this RunOnDrop.
44    #[inline(always)]
45    pub fn new(value: T, function: F) -> Self {
46        Self {
47            value: ManuallyDrop::new(value),
48            function: ManuallyDrop::new(function),
49        }
50    }
51}
52
53impl<T, F> RunOnDrop<T, F>
54where
55    F: FnOnce(T),
56{
57    /// Reborrows the wrapped value.
58    #[inline(always)]
59    pub fn get(&self) -> &T {
60        &*self.value
61    }
62
63    /// Reborrows the wrapped value mutably.
64    #[inline(always)]
65    pub fn get_mut(&mut self) -> &mut T {
66        &mut *self.value
67    }
68
69    /// Extracts the wrapped value, preventing the closure from running at the end of the scope.
70    pub fn into_inner(self) -> T {
71        let mut this = ManuallyDrop::new(self);
72        unsafe{
73            let ret = take_manuallydrop(&mut this.value);
74            ManuallyDrop::drop(&mut this.function);
75            ret
76        }
77    }
78
79}
80
81impl<T, F> Drop for RunOnDrop<T, F>
82where
83    F: FnOnce(T),
84{
85    #[inline(always)]
86    fn drop(&mut self) {
87        unsafe {
88            let value = take_manuallydrop(&mut self.value);
89            let function = take_manuallydrop(&mut self.function);
90            function(value);
91        }
92    }
93}
94
95
96