after_drop/
lib.rs

1//! This will run when is droped
2//!
3//! This will run in drop order, that means newest first
4//!
5//! ## features:
6//!
7//! - default = ["std"]
8//! - std
9//!
10//! use `default-features=false` if you don't want std
11
12#![cfg_attr(not(feature = "std"), no_std)]
13
14/// A simple continer for the defer function that is called on drop!
15
16pub struct AfterDrop<F: FnOnce()>(Option<F>);
17
18pub fn defer<F: FnOnce()>(func: F) -> AfterDrop<F> {
19    AfterDrop::new(func)
20}
21
22impl<F: FnOnce()> AfterDrop<F> {
23    #[must_use]
24    pub fn new(func: F) -> Self {
25        Self(Some(func))
26    }
27}
28
29impl<F: FnOnce()> Drop for AfterDrop<F> {
30    fn drop(&mut self) {
31        self.0.take().unwrap()()
32    }
33}
34
35impl<F: FnOnce()> From<F> for AfterDrop<F> {
36    fn from(func: F) -> Self {
37        Self::new(func)
38    }
39}
40
41/// This is a boxed version to be stored easier!
42
43#[cfg(feature = "std")]
44pub struct AfterDropBoxed<'a>(Option<Box<dyn FnOnce() + 'a>>);
45
46#[cfg(feature = "std")]
47impl<'a> AfterDropBoxed<'a> {
48    #[must_use]
49    pub fn new<F: FnOnce() + 'a>(func: F) -> Self {
50        Self(Some(Box::new(func)))
51    }
52}
53
54#[cfg(feature = "std")]
55impl<'a> Drop for AfterDropBoxed<'a> {
56    fn drop(&mut self) {
57        self.0.take().unwrap()()
58    }
59}
60
61#[cfg(feature = "std")]
62impl<'a, F: FnOnce() + 'a> From<F> for AfterDropBoxed<'a> {
63    fn from(func: F) -> Self {
64        Self::new(func)
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    #[test]
71    fn defer() {
72        let mut droped = false;
73
74        let _defer = crate::defer(|| droped = true);
75        drop(_defer);
76
77        assert!(droped)
78    }
79
80    #[test]
81    fn drop_after_boxed() {
82        let mut droped = false;
83
84        let _boxed = crate::AfterDropBoxed::new(|| droped = true);
85        drop(_boxed);
86
87        assert!(droped);
88    }
89}