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    /// # Returns
21    ///
22    /// - `&'static mut HookContextInner` - A mutable reference to the inner state.
23    pub(crate) fn get_inner(&self) -> &'static mut HookContextInner {
24        unsafe { &mut *self.inner }
25    }
26
27    /// Resets the hook index for a new render cycle.
28    ///
29    /// Sets the hook index back to `0` so that subsequent hook calls
30    /// re-associate with their stored state by call order.
31    pub fn reset_hook_index(&mut self) {
32        self.get_inner().set_hook_index(0);
33    }
34
35    /// Notifies the hook context that a match arm is being entered.
36    /// Toggles the `arm_changed` flag; if it differs from the previous value,
37    /// the hooks array is cleared to prevent signal leakage between arms.
38    ///
39    /// # Arguments
40    ///
41    /// - `bool` - The new arm changed state.
42    pub fn set_arm_changed(&mut self, changed: bool) {
43        let inner: &mut HookContextInner = self.get_inner();
44        if inner.get_arm_changed() != changed {
45            let cleanups: Vec<Box<dyn FnOnce()>> = take(inner.get_mut_cleanups());
46            for cleanup in cleanups {
47                cleanup();
48            }
49            inner.get_mut_hooks().clear();
50            inner.set_arm_changed(changed);
51        }
52        self.reset_hook_index();
53    }
54}
55
56/// Clones the hook context, sharing the same inner state.
57impl Clone for HookContext {
58    /// Returns a bitwise copy of this hook context.
59    fn clone(&self) -> Self {
60        *self
61    }
62}
63
64/// Copies the hook context, sharing the same inner state.
65///
66/// A `HookContext` is just a raw pointer; copying it is a trivial bitwise copy.
67impl Copy for HookContext {}
68
69/// Provides a default empty hook context.
70impl Default for HookContext {
71    /// Returns a default `HookContext` by allocating a new empty inner via `Box::leak`.
72    fn default() -> Self {
73        let boxed: Box<HookContextInner> = Box::default();
74        HookContext::from_inner(Box::leak(boxed) as *mut HookContextInner)
75    }
76}
77
78/// Implementation of HookContextInner construction.
79impl HookContextInner {
80    /// Creates a new empty hook context inner.
81    ///
82    /// # Returns
83    ///
84    /// - `Self` - A new hook context inner with empty hooks and cleanups.
85    pub const fn new() -> Self {
86        HookContextInner {
87            hooks: Vec::new(),
88            arm_changed: false,
89            hook_index: 0_usize,
90            cleanups: Vec::new(),
91        }
92    }
93}
94
95/// Provides a default empty hook context inner.
96impl Default for HookContextInner {
97    /// Returns a default `HookContextInner` by delegating to `HookContextInner::new`.
98    fn default() -> Self {
99        Self::new()
100    }
101}
102
103/// Implementation of HookContextCell construction and access.
104impl HookContextCell {
105    /// Returns a mutable reference to the inner `HookContextInner`.
106    ///
107    /// # Returns
108    ///
109    /// - `&'static mut HookContextInner` - A mutable reference to the inner state.
110    pub const fn get_inner(&self) -> &'static mut HookContextInner {
111        unsafe { &mut *self.0.get() }
112    }
113}
114
115/// SAFETY: `HookContextCell` is only used in single-threaded WASM contexts.
116/// Concurrent access from multiple threads would be undefined behavior.
117unsafe impl Sync for HookContextCell {}