1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use *;
/// A `Sync` wrapper holding a single value of type `T`.
///
/// ## Storage convention
///
/// This type aligns with the rest of the engine's `static mut`
/// convention used in `core::reactive::hook::impl`. The companion
/// storage helpers `try_get` / `try_get_mut` / `get` / `get_mut`
/// return `&'static mut T` and rely on the caller to honour the
/// single-writer contract. The engine is compiled for
/// `wasm32-unknown-unknown` which is single-threaded by contract,
/// so overlapping borrows violate the caller contract rather than
/// being trapped at runtime the way `RefCell` would.
///
/// `RefCell` is intentionally **not** used as the storage backend:
/// its runtime aliasing panic is unreachable in practice under
/// wasm's single-threaded model and adds code size and a redundant
/// safety net that the rest of the codebase does not provide.
///
/// ## `?Sized` bound and trait-object storage
///
/// The `T: ?Sized` bound is what lets the engine alias
/// `Rc<EngineCell<dyn Trait>>` directly (see `ComponentRc`,
/// `SceneRc`, `TickHandlerRc` in their respective `type.rs`). The
/// trait-object fat pointer is stored in-place inside the
/// `UnsafeCell<T>`; `get_mut -> &'static mut dyn Trait` lets
/// callers dispatch without an intermediate `Box`.
///
/// ## When to choose this vs [`MaybeEngineCell`]
///
/// The cell has no notion of "uninitialized" - use [`MaybeEngineCell`]
/// if the value may legitimately be absent (the typical case for
/// "global installed at mount, torn down at unmount" singletons).
/// For always-present values this is a zero-overhead wrapper around
/// `UnsafeCell<T>`.
///
/// ## Field access rule
///
/// The `inner` field is reached through the hand-written
/// `get_inner` / `set_inner` accessors declared in `cell/impl.rs`.
/// All read sites in this module call `get_inner().get()` and write
/// sites use `set_inner(UnsafeCell::new(value))` rather than touching
/// the field directly. Struct literals `Self { inner: ... }` are
/// permitted only inside the `new` constructor and the `Default`
/// impl, per the engine's "exceptions to no-direct-field-access"
/// convention.
///
/// ## Note on `#[derive(Data)]`
///
/// Lombok's `Data` derive is intentionally **not** applied here:
/// the derive requires `T: Sized`, which would defeat the `?Sized`
/// bound above and break the engine's `Rc<EngineCell<dyn Trait>>`
/// aliases. The accessor pair is hand-written in `cell/impl.rs`
/// with the same Lombok-style contract.
/// A `Sync` wrapper that may or may not contain a value.
///
/// ## When to choose this vs [`EngineCell`]
///
/// Use this when the global state has a clear "not yet installed" or
/// "already torn down" state. Access is gated on the inner `Option`
/// being `Some`, so all the `try_*` accessors return `Option<...>`,
/// matching `core::reactive::hook::try_get_current`'s wording.
///
/// ## Field access rule
///
/// Same as [`EngineCell`]: `inner` is reached only through the
/// hand-written `get_inner` / `set_inner` accessors; the
/// struct-literal escape hatch is reserved for the `new` / `default`
/// constructors.