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 pub fn leak_mut(&self) -> &'static mut HookContextInner {
97 let address: usize = (*self).into();
98 address.into()
99 }
100
101 /// Resets the hook index for a new render cycle.
102 ///
103 /// Sets the hook index back to `0` so that subsequent hook calls
104 /// re-associate with their stored state by call order.
105 pub fn reset_hook_index(&mut self) {
106 self.leak_mut().set_hook_index(0);
107 }
108
109 /// Notifies the hook context that a match arm is being entered.
110 /// Sets the `arm_changed` to the arm index; if it differs from the previous value,
111 /// the hooks array is cleared to prevent signal leakage between arms.
112 ///
113 /// # Arguments
114 ///
115 /// - `usize` - The match arm index.
116 pub fn set_arm_changed(&mut self, changed: usize) {
117 let inner: &mut HookContextInner = self.leak_mut();
118 if inner.get_arm_changed() != changed {
119 let cleanups: Vec<Box<dyn FnOnce()>> = take(inner.get_mut_cleanups());
120 for cleanup in cleanups {
121 cleanup();
122 }
123 inner.get_mut_hooks().clear();
124 inner.set_arm_changed(changed);
125 }
126 self.reset_hook_index();
127 }
128}
129
130/// Clones the hook context, sharing the same inner state.
131impl Clone for HookContext {
132 /// Returns a bitwise copy of this hook context.
133 fn clone(&self) -> Self {
134 *self
135 }
136}
137
138/// Copies the hook context, sharing the same inner state.
139///
140/// A `HookContext` is just a raw pointer; copying it is a trivial bitwise copy.
141impl Copy for HookContext {}
142
143/// Provides a default empty hook context.
144impl Default for HookContext {
145 /// Returns a default `HookContext` by allocating a new empty inner via `Box::leak`.
146 fn default() -> Self {
147 let boxed: Box<HookContextInner> = Box::default();
148 let ptr: *mut HookContextInner = Box::leak(boxed) as *mut HookContextInner;
149 let address: usize = ptr as usize;
150 address.into()
151 }
152}
153
154/// Implementation of HookContextInner construction.
155impl HookContextInner {
156 /// Creates a new empty hook context inner.
157 ///
158 /// # Returns
159 ///
160 /// - `Self` - A new hook context inner with empty hooks and cleanups.
161 pub const fn new() -> Self {
162 HookContextInner {
163 hooks: Vec::new(),
164 arm_changed: 0,
165 hook_index: 0,
166 cleanups: Vec::new(),
167 }
168 }
169}
170
171/// Provides a default empty hook context inner.
172impl Default for HookContextInner {
173 /// Returns a default `HookContextInner` by delegating to `HookContextInner::new`.
174 fn default() -> Self {
175 Self::new()
176 }
177}
178
179/// Implementation of HookContextCell construction and access.
180impl HookContextCell {
181 /// Returns a mutable reference to the inner `HookContextInner`.
182 ///
183 /// # Returns
184 ///
185 /// - `&'static mut HookContextInner` - A mutable reference to the inner state.
186 pub const fn get_inner(&self) -> &'static mut HookContextInner {
187 unsafe { &mut *self.0.get() }
188 }
189}
190
191/// SAFETY: `HookContextCell` is only used in single-threaded WASM contexts.
192/// Concurrent access from multiple threads would be undefined behavior.
193unsafe impl Sync for HookContextCell {}