1#[must_use = "if unused the deferred action will execute immediately"]
9pub struct Deferred<F: FnOnce()> {
10 action: Option<F>,
11}
12
13impl<F: FnOnce()> Deferred<F> {
14 #[inline]
16 pub const fn new(action: F) -> Self {
17 Self { action: Some(action) }
18 }
19
20 #[inline]
22 pub fn cancel(&mut self) {
23 self.action = None;
24 }
25
26 #[inline]
28 pub fn call(&mut self) {
29 if let Some(action) = self.action.take() {
30 action();
31 }
32 }
33}
34
35impl<F: FnOnce()> Drop for Deferred<F> {
36 #[inline]
37 fn drop(&mut self) {
38 if let Some(action) = self.action.take() {
39 action();
40 }
41 }
42}
43
44#[inline]
49pub fn defer<F: FnOnce()>(action: F) -> Deferred<F> {
50 Deferred::new(action)
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn test_defer_runs_on_drop() {
59 let mut executed = false;
60 {
61 let _guard = defer(|| {
62 executed = true;
63 });
64 assert!(!executed);
65 }
66 assert!(executed);
67 }
68
69 #[test]
70 fn test_defer_cancel() {
71 let mut executed = false;
72 {
73 let mut guard = defer(|| {
74 executed = true;
75 });
76 guard.cancel();
77 }
78 assert!(!executed);
79 }
80
81 #[test]
82 fn test_defer_call_early() {
83 let mut count = 0;
84 {
85 let mut guard = defer(|| {
86 count += 1;
87 });
88 assert_eq!(count, 0);
89 guard.call();
90 assert_eq!(count, 1);
91 }
92 assert_eq!(count, 1);
94 }
95}