nexus_rt/resource.rs
1//! Shared and mutable resource references for handler parameters.
2//!
3//! [`Res<T>`] and [`ResMut<T>`] appear in handler function signatures to
4//! declare read and write dependencies on [`World`](crate::World) resources.
5//! They are produced by [`Param::fetch`](crate::Param::fetch) during dispatch
6//! and deref to the inner `T` transparently.
7//!
8//! For optional dependencies, use [`Option<Res<T>>`] or
9//! [`Option<ResMut<T>>`] — these resolve to `None` if the type was not
10//! registered, rather than panicking at build time.
11//!
12//! # Examples
13//!
14//! ```
15//! use nexus_rt::{WorldBuilder, Res, ResMut, IntoHandler, Handler, Resource};
16//!
17//! #[derive(Resource)]
18//! struct Config(u64);
19//! #[derive(Resource)]
20//! struct Flag(bool);
21//!
22//! fn process(config: Res<Config>, mut state: ResMut<Flag>, _event: ()) {
23//! if config.0 > 10 {
24//! state.0 = true;
25//! }
26//! }
27//!
28//! let mut builder = WorldBuilder::new();
29//! builder.register(Config(42));
30//! builder.register(Flag(false));
31//! let mut world = builder.build();
32//!
33//! let mut handler = process.into_handler(world.registry());
34//! handler.run(&mut world, ());
35//!
36//! assert!(world.resource::<Flag>().0);
37//! ```
38
39use std::cell::Cell;
40use std::ops::{Deref, DerefMut};
41
42use crate::Resource;
43use crate::world::Sequence;
44
45/// Shared reference to a resource in [`World`](crate::World).
46///
47/// Analogous to Bevy's `Res<T>`.
48///
49/// Appears in handler function signatures to declare a read dependency.
50/// Derefs to the inner value transparently.
51///
52/// For exclusive write access, use [`ResMut<T>`]. For optional read
53/// access (no panic if unregistered), use [`Option<Res<T>>`].
54///
55/// Construction is `pub(crate)` — only the dispatch layer creates these.
56pub struct Res<'w, T: Resource> {
57 value: &'w T,
58}
59
60impl<'w, T: Resource> Res<'w, T> {
61 pub(crate) fn new(value: &'w T) -> Self {
62 Self { value }
63 }
64}
65
66impl<T: std::fmt::Debug + Resource> std::fmt::Debug for Res<'_, T> {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 self.value.fmt(f)
69 }
70}
71
72impl<T: Resource> Deref for Res<'_, T> {
73 type Target = T;
74
75 #[inline(always)]
76 fn deref(&self) -> &T {
77 self.value
78 }
79}
80
81/// Mutable reference to a resource in [`World`](crate::World).
82///
83/// Analogous to Bevy's `ResMut<T>`.
84///
85/// Appears in handler function signatures to declare a write dependency.
86/// Derefs to the inner value transparently.
87///
88/// For shared read access, use [`Res<T>`]. For optional write access
89/// (no panic if unregistered), use [`Option<ResMut<T>>`].
90///
91/// Construction is `pub(crate)` — only the dispatch layer creates these.
92pub struct ResMut<'w, T: Resource> {
93 value: &'w mut T,
94}
95
96impl<'w, T: Resource> ResMut<'w, T> {
97 pub(crate) fn new(value: &'w mut T) -> Self {
98 Self { value }
99 }
100}
101
102impl<T: std::fmt::Debug + Resource> std::fmt::Debug for ResMut<'_, T> {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 self.value.fmt(f)
105 }
106}
107
108impl<T: Resource> Deref for ResMut<'_, T> {
109 type Target = T;
110
111 #[inline(always)]
112 fn deref(&self) -> &T {
113 self.value
114 }
115}
116
117impl<T: Resource> DerefMut for ResMut<'_, T> {
118 #[inline(always)]
119 fn deref_mut(&mut self) -> &mut T {
120 self.value
121 }
122}
123
124// =============================================================================
125// Seq / SeqMut — sequence number access
126// =============================================================================
127
128/// Read-only access to the world's current sequence number.
129///
130/// Appears in handler function signatures alongside other params.
131/// Derefs to [`Sequence`].
132///
133/// # Example
134///
135/// ```ignore
136/// use nexus_rt::{Seq, Handler, IntoHandler};
137///
138/// fn log_event(seq: Seq, event: u64) {
139/// println!("event {} at sequence {}", event, seq.get());
140/// }
141/// ```
142#[derive(Clone, Copy)]
143pub struct Seq(pub(crate) Sequence);
144
145impl Seq {
146 /// Returns the current sequence value.
147 #[inline(always)]
148 pub const fn get(&self) -> i64 {
149 self.0.get()
150 }
151}
152
153impl Deref for Seq {
154 type Target = Sequence;
155
156 #[inline(always)]
157 fn deref(&self) -> &Sequence {
158 &self.0
159 }
160}
161
162/// Mutable access to the world's current sequence number.
163///
164/// Allows handlers to advance the sequence — useful for stamping
165/// outbound messages with monotonic sequence numbers.
166///
167/// # Example
168///
169/// ```ignore
170/// use nexus_rt::{SeqMut, Handler, IntoHandler};
171///
172/// fn send_message(mut seq: SeqMut<'_>, event: u64) {
173/// let msg_seq = seq.advance();
174/// // stamp msg_seq on outbound message
175/// }
176/// ```
177pub struct SeqMut<'w>(pub(crate) &'w Cell<Sequence>);
178
179impl SeqMut<'_> {
180 /// Returns the current sequence value.
181 #[inline(always)]
182 pub fn get(&self) -> Sequence {
183 self.0.get()
184 }
185
186 /// Advance the sequence by 1 and return the new value.
187 #[inline(always)]
188 pub fn advance(&mut self) -> Sequence {
189 let next = Sequence(self.0.get().0.wrapping_add(1));
190 self.0.set(next);
191 next
192 }
193}
194
195// =============================================================================
196// Tests
197// =============================================================================
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202 use crate::world::Resource;
203
204 struct Val(u64);
205 impl Resource for Val {}
206
207 #[test]
208 fn res_deref() {
209 let val = Val(42);
210 let res = Res::new(&val);
211 assert_eq!(res.0, 42);
212 }
213
214 #[test]
215 fn res_mut_deref() {
216 let mut val = Val(0);
217 let mut res = ResMut::new(&mut val);
218 res.0 = 99;
219 assert_eq!(val.0, 99);
220 }
221
222 #[test]
223 fn res_mut_deref_mut_no_stamp() {
224 // ResMut::deref_mut is now a plain pass-through — no stamping.
225 let mut val = Val(0);
226 let mut res = ResMut::new(&mut val);
227 *res = Val(123);
228 assert_eq!(val.0, 123);
229 }
230
231 #[test]
232 fn seq_get() {
233 let seq = Seq(Sequence(42));
234 assert_eq!(seq.get(), 42);
235 }
236
237 #[test]
238 fn seq_mut_advance() {
239 let cell = Cell::new(Sequence(0));
240 let mut seq = SeqMut(&cell);
241 let next = seq.advance();
242 assert_eq!(next, Sequence(1));
243 assert_eq!(cell.get(), Sequence(1));
244 }
245}