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 {}