nexus/revertible.rs
1use crate::on_unload;
2
3/// A revertible action.
4///
5/// Returned by several functions registering callbacks that may have to be unregistered later.
6/// This type is marked as `must_use` to force being explicit about handling reversions.
7///
8/// There several ways to deal with a received [`Revertible`]:
9/// - Call [`revert_on_unload`](Revertible::revert_on_unload) to automatically revert on addon unload.
10/// - Call [`leak`](Revertible::leak) or drop it (explicitly or implicitly) to discard and unregister manually.
11/// - Keep the [`Revertible`] and call [`revert`](Revertible::revert) later.
12/// - Turn it into a callable via [`into_inner`](Revertible::into_inner) and call it later.
13#[must_use]
14#[derive(Debug)]
15#[repr(transparent)]
16pub struct Revertible<F>
17where
18 F: FnOnce() + Send + 'static,
19{
20 revert: F,
21}
22
23impl<F> Revertible<F>
24where
25 F: FnOnce() + Send + 'static,
26{
27 /// Creates a new revertible action.
28 #[inline]
29 pub const fn new(revert: F) -> Self {
30 Self { revert }
31 }
32
33 /// Turns the revertible into the inner callable.
34 #[inline]
35 #[must_use]
36 pub fn into_inner(self) -> F {
37 self.revert
38 }
39
40 /// Leaves the action to not be reverted.
41 ///
42 /// The reversion has to be performed manually.
43 /// Effectively the same as dropping the revertible.
44 #[inline]
45 pub fn leak(self) {}
46
47 /// Reverts the action.
48 #[inline]
49 pub fn revert(self) {
50 (self.revert)()
51 }
52
53 /// Submits the revertible to be reverted on unload.
54 #[inline]
55 pub fn revert_on_unload(self) {
56 on_unload(self.into_inner())
57 }
58}
59
60impl<F> From<F> for Revertible<F>
61where
62 F: FnOnce() + Send + 'static,
63{
64 #[inline]
65 fn from(revert: F) -> Self {
66 Self::new(revert)
67 }
68}