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}