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