Skip to main content

euv_core/reactive/hook/
impl.rs

1use crate::*;
2
3/// Implementation of hook context lifecycle and hook index management.
4impl HookContext {
5    /// Creates a new `HookContext` from an existing raw pointer.
6    ///
7    /// # Arguments
8    ///
9    /// - `*mut HookContextInner` - A raw pointer to the heap-allocated hook context inner state.
10    ///
11    /// # Returns
12    ///
13    /// - `Self` - A hook context handle wrapping the given pointer.
14    pub fn from_inner(inner: *mut HookContextInner) -> Self {
15        HookContext { inner }
16    }
17
18    /// Returns a mutable reference to the inner hook context state.
19    ///
20    /// # Safety
21    ///
22    /// The caller must ensure no other references to the inner state exist.
23    /// In single-threaded WASM this is always safe.
24    #[allow(clippy::mut_from_ref)]
25    fn get_inner_mut(&self) -> &mut HookContextInner {
26        unsafe { &mut *self.inner }
27    }
28
29    /// Returns the current hook index.
30    ///
31    /// # Returns
32    ///
33    /// - `usize` - The current hook index.
34    pub fn get_hook_index(&self) -> usize {
35        self.get_inner_mut().get_hook_index()
36    }
37
38    /// Sets the hook index.
39    ///
40    /// # Arguments
41    ///
42    /// - `usize` - The new hook index value.
43    pub fn set_hook_index(&mut self, index: usize) {
44        self.get_inner_mut().set_hook_index(index);
45    }
46
47    /// Returns a reference to the hooks storage.
48    ///
49    /// # Returns
50    ///
51    /// - `&Vec<Box<dyn Any>>` - A reference to the hooks storage.
52    pub fn get_hooks(&self) -> &Vec<Box<dyn Any>> {
53        self.get_inner_mut().get_hooks()
54    }
55
56    /// Returns a mutable reference to the hooks storage.
57    ///
58    /// # Returns
59    ///
60    /// - `&mut Vec<Box<dyn Any>>` - A mutable reference to the hooks storage.
61    pub fn get_mut_hooks(&mut self) -> &mut Vec<Box<dyn Any>> {
62        self.get_inner_mut().get_mut_hooks()
63    }
64
65    /// Returns a mutable reference to the cleanup closures storage.
66    ///
67    /// # Returns
68    ///
69    /// - `&mut Vec<Box<dyn FnOnce()>>` - A mutable reference to the cleanup closures storage.
70    pub fn get_mut_cleanups(&mut self) -> &mut Vec<Box<dyn FnOnce()>> {
71        self.get_inner_mut().get_mut_cleanups()
72    }
73
74    /// Resets the hook index for a new render cycle.
75    ///
76    /// Sets the hook index back to `0` so that subsequent hook calls
77    /// re-associate with their stored state by call order.
78    pub fn reset_hook_index(&mut self) {
79        self.set_hook_index(0_usize);
80    }
81
82    /// Notifies the hook context that a match arm is being entered.
83    /// Toggles the `arm_changed` flag; if it differs from the previous value,
84    /// the hooks array is cleared to prevent signal leakage between arms.
85    ///
86    /// # Arguments
87    ///
88    /// - `bool` - The new arm changed state.
89    pub fn set_arm_changed(&mut self, changed: bool) {
90        let inner: &mut HookContextInner = self.get_inner_mut();
91        if inner.get_arm_changed() != changed {
92            let cleanups: Vec<Box<dyn FnOnce()>> = std::mem::take(inner.get_mut_cleanups());
93            for cleanup in cleanups {
94                cleanup();
95            }
96            inner.get_mut_hooks().clear();
97            inner.set_arm_changed(changed);
98        }
99        self.reset_hook_index();
100    }
101}
102
103/// Clones the hook context, sharing the same inner state.
104impl Clone for HookContext {
105    /// Returns a bitwise copy of this hook context.
106    fn clone(&self) -> Self {
107        *self
108    }
109}
110
111/// Copies the hook context, sharing the same inner state.
112///
113/// A `HookContext` is just a raw pointer; copying it is a trivial bitwise copy.
114impl Copy for HookContext {}
115
116/// Provides a default empty hook context.
117impl Default for HookContext {
118    /// Returns a default `HookContext` by allocating a new empty inner via `Box::leak`.
119    fn default() -> Self {
120        let boxed: Box<HookContextInner> = Box::default();
121        HookContext::from_inner(Box::leak(boxed) as *mut HookContextInner)
122    }
123}
124
125/// Implementation of HookContextInner construction.
126impl HookContextInner {
127    /// Creates a new empty hook context inner.
128    ///
129    /// # Returns
130    ///
131    /// - `Self` - A new hook context inner with empty hooks and cleanups.
132    pub const fn new() -> Self {
133        HookContextInner {
134            hooks: Vec::new(),
135            arm_changed: false,
136            hook_index: 0_usize,
137            cleanups: Vec::new(),
138        }
139    }
140}
141
142/// Provides a default empty hook context inner.
143impl Default for HookContextInner {
144    /// Returns a default `HookContextInner` by delegating to `HookContextInner::new`.
145    fn default() -> Self {
146        Self::new()
147    }
148}
149
150/// SAFETY: `HookContextCell` is only used in single-threaded WASM contexts.
151/// Concurrent access from multiple threads would be undefined behavior.
152unsafe impl Sync for HookContextCell {}