Skip to main content

euv_core/reactive/hook/
impl.rs

1use crate::*;
2
3/// Implementation of `From` trait for converting `usize` address into `&'static mut HookContextInner`.
4impl From<usize> for &'static mut HookContextInner {
5    /// Converts a memory address into a mutable reference to `HookContextInner`.
6    ///
7    /// # Arguments
8    ///
9    /// - `usize` - The memory address of the `HookContextInner` instance.
10    ///
11    /// # Returns
12    ///
13    /// - `&'static mut HookContextInner` - A mutable reference to the `HookContextInner` at the given address.
14    ///
15    /// # Safety
16    ///
17    /// - The address is guaranteed to be a valid `HookContextInner` instance
18    ///   that was previously converted from a reference and is managed by the runtime.
19    #[inline(always)]
20    fn from(address: usize) -> Self {
21        unsafe { &mut *(address as *mut HookContextInner) }
22    }
23}
24
25/// Implementation of `From` trait for converting `usize` address into `&'static HookContextInner`.
26impl From<usize> for &'static HookContextInner {
27    /// Converts a memory address into a reference to `HookContextInner`.
28    ///
29    /// # Arguments
30    ///
31    /// - `usize` - The memory address of the `HookContextInner` instance.
32    ///
33    /// # Returns
34    ///
35    /// - `&'static HookContextInner` - A reference to the `HookContextInner` at the given address.
36    ///
37    /// # Safety
38    ///
39    /// - The address is guaranteed to be a valid `HookContextInner` instance
40    ///   that was previously converted from a reference and is managed by the runtime.
41    #[inline(always)]
42    fn from(address: usize) -> Self {
43        unsafe { &*(address as *const HookContextInner) }
44    }
45}
46
47/// Implementation of `From` trait for converting `HookContext` into `usize` address.
48impl From<HookContext> for usize {
49    /// Converts a `HookContext` into its memory address.
50    ///
51    /// # Arguments
52    ///
53    /// - `HookContext` - The hook context handle.
54    ///
55    /// # Returns
56    ///
57    /// - `usize` - The memory address of the hook context's inner state.
58    #[inline(always)]
59    fn from(context: HookContext) -> Self {
60        context.inner as usize
61    }
62}
63
64/// Implementation of `From` trait for converting `usize` address into `HookContext`.
65impl From<usize> for HookContext {
66    /// Converts a memory address into a `HookContext` handle.
67    ///
68    /// # Arguments
69    ///
70    /// - `usize` - The memory address previously obtained from `HookContext` conversion.
71    ///
72    /// # Returns
73    ///
74    /// - `HookContext` - A hook context handle wrapping the pointer at the given address.
75    ///
76    /// # Safety
77    ///
78    /// - The address is guaranteed to be a valid `HookContextInner` instance
79    ///   that was previously converted from a hook context handle and is managed by the runtime.
80    #[inline(always)]
81    fn from(address: usize) -> Self {
82        HookContext {
83            inner: address as *mut HookContextInner,
84        }
85    }
86}
87
88/// Implementation of hook context lifecycle and hook index management.
89impl HookContext {
90    /// Returns a mutable reference to the inner hook context state by going
91    /// through `usize` intermediate conversion.
92    ///
93    /// # Returns
94    ///
95    /// - `&'static mut HookContextInner` - A mutable reference to the inner state.
96    #[allow(clippy::mut_from_ref)]
97    pub fn leak_mut(&self) -> &'static mut HookContextInner {
98        let address: usize = (*self).into();
99        address.into()
100    }
101
102    /// Resets the hook index for a new render cycle.
103    ///
104    /// Sets the hook index back to `0` so that subsequent hook calls
105    /// re-associate with their stored state by call order.
106    pub fn reset_hook_index(&mut self) {
107        self.leak_mut().set_hook_index(0);
108    }
109
110    /// Notifies the hook context that a match arm is being entered.
111    /// Toggles the `arm_changed` flag; if it differs from the previous value,
112    /// the hooks array is cleared to prevent signal leakage between arms.
113    ///
114    /// # Arguments
115    ///
116    /// - `bool` - The new arm changed state.
117    pub fn set_arm_changed(&mut self, changed: bool) {
118        let inner: &mut HookContextInner = self.leak_mut();
119        if inner.get_arm_changed() != changed {
120            let cleanups: Vec<Box<dyn FnOnce()>> = take(inner.get_mut_cleanups());
121            for cleanup in cleanups {
122                cleanup();
123            }
124            inner.get_mut_hooks().clear();
125            inner.set_arm_changed(changed);
126        }
127        self.reset_hook_index();
128    }
129}
130
131/// Clones the hook context, sharing the same inner state.
132impl Clone for HookContext {
133    /// Returns a bitwise copy of this hook context.
134    fn clone(&self) -> Self {
135        *self
136    }
137}
138
139/// Copies the hook context, sharing the same inner state.
140///
141/// A `HookContext` is just a raw pointer; copying it is a trivial bitwise copy.
142impl Copy for HookContext {}
143
144/// Provides a default empty hook context.
145impl Default for HookContext {
146    /// Returns a default `HookContext` by allocating a new empty inner via `Box::leak`.
147    fn default() -> Self {
148        let boxed: Box<HookContextInner> = Box::default();
149        let ptr: *mut HookContextInner = Box::leak(boxed) as *mut HookContextInner;
150        let address: usize = ptr as usize;
151        address.into()
152    }
153}
154
155/// Implementation of HookContextInner construction.
156impl HookContextInner {
157    /// Creates a new empty hook context inner.
158    ///
159    /// # Returns
160    ///
161    /// - `Self` - A new hook context inner with empty hooks and cleanups.
162    pub const fn new() -> Self {
163        HookContextInner {
164            hooks: Vec::new(),
165            arm_changed: false,
166            hook_index: 0_usize,
167            cleanups: Vec::new(),
168        }
169    }
170}
171
172/// Provides a default empty hook context inner.
173impl Default for HookContextInner {
174    /// Returns a default `HookContextInner` by delegating to `HookContextInner::new`.
175    fn default() -> Self {
176        Self::new()
177    }
178}
179
180/// Implementation of HookContextCell construction and access.
181impl HookContextCell {
182    /// Returns a mutable reference to the inner `HookContextInner`.
183    ///
184    /// # Returns
185    ///
186    /// - `&'static mut HookContextInner` - A mutable reference to the inner state.
187    pub const fn get_inner(&self) -> &'static mut HookContextInner {
188        unsafe { &mut *self.0.get() }
189    }
190}
191
192/// SAFETY: `HookContextCell` is only used in single-threaded WASM contexts.
193/// Concurrent access from multiple threads would be undefined behavior.
194unsafe impl Sync for HookContextCell {}