Skip to main content

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, no_event};
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>) {
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 = no_event(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/// # Cloning
53///
54/// `Res<T>` is `Copy + Clone` regardless of `T` — the wrapped reference
55/// is `&T`, which is always `Copy`. To clone the *inner* value, use
56/// `(*res).clone()` or `res.to_owned()`. Calling `res.clone()` returns
57/// `Res<T>`, not `T` — same shadowing pattern as Bevy's `Res<T>`.
58///
59/// For exclusive write access, use [`ResMut<T>`]. For optional read
60/// access (no panic if unregistered), use [`Option<Res<T>>`].
61///
62/// Construction is `pub(crate)` — only the dispatch layer creates these.
63pub struct Res<'w, T: Resource> {
64    value: &'w T,
65}
66
67impl<'w, T: Resource> Res<'w, T> {
68    pub(crate) fn new(value: &'w T) -> Self {
69        Self { value }
70    }
71}
72
73// Manual Copy/Clone impls (not derived) so the bounds depend only on what
74// the field actually requires. The single field is `&T`, which is always
75// Copy regardless of `T`. A derive would erroneously add `T: Clone`.
76impl<T: Resource> Clone for Res<'_, T> {
77    #[inline(always)]
78    fn clone(&self) -> Self {
79        *self
80    }
81}
82
83impl<T: Resource> Copy for Res<'_, T> {}
84
85impl<T: std::fmt::Debug + Resource> std::fmt::Debug for Res<'_, T> {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        self.value.fmt(f)
88    }
89}
90
91impl<T: Resource> Deref for Res<'_, T> {
92    type Target = T;
93
94    #[inline(always)]
95    fn deref(&self) -> &T {
96        self.value
97    }
98}
99
100/// Mutable reference to a resource in [`World`](crate::World).
101///
102/// Analogous to Bevy's `ResMut<T>`.
103///
104/// Appears in handler function signatures to declare a write dependency.
105/// Derefs to the inner value transparently.
106///
107/// # Passing by value
108///
109/// `ResMut<T>` cannot be `Copy` (exclusive borrow). To pass the wrapper
110/// to inner functions without moving, call [`reborrow()`](Self::reborrow)
111/// — analogous to the `&mut *x` pattern for `&mut T`.
112///
113/// For shared read access, use [`Res<T>`]. For optional write access
114/// (no panic if unregistered), use [`Option<ResMut<T>>`].
115///
116/// Construction is `pub(crate)` — only the dispatch layer creates these.
117pub struct ResMut<'w, T: Resource> {
118    value: &'w mut T,
119}
120
121impl<'w, T: Resource> ResMut<'w, T> {
122    pub(crate) fn new(value: &'w mut T) -> Self {
123        Self { value }
124    }
125
126    /// Reborrow as a `ResMut<'_, T>` with a shorter lifetime.
127    ///
128    /// The original is frozen for the duration of the reborrow, then usable
129    /// again. Lets you pass `ResMut<T>` to inner functions without moving —
130    /// analogous to the `&mut *x` reborrow pattern for `&mut T`.
131    ///
132    /// `ResMut<T>` cannot be `Copy` (exclusive borrow), so this is the
133    /// counterpart to [`Res<T>`]'s `Copy` impl when the inner function
134    /// signature takes the wrapper itself rather than `&mut T`.
135    #[inline(always)]
136    pub fn reborrow(&mut self) -> ResMut<'_, T> {
137        ResMut {
138            value: &mut *self.value,
139        }
140    }
141}
142
143impl<T: std::fmt::Debug + Resource> std::fmt::Debug for ResMut<'_, T> {
144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145        self.value.fmt(f)
146    }
147}
148
149impl<T: Resource> Deref for ResMut<'_, T> {
150    type Target = T;
151
152    #[inline(always)]
153    fn deref(&self) -> &T {
154        self.value
155    }
156}
157
158impl<T: Resource> DerefMut for ResMut<'_, T> {
159    #[inline(always)]
160    fn deref_mut(&mut self) -> &mut T {
161        self.value
162    }
163}
164
165// =============================================================================
166// Seq / SeqMut — sequence number access
167// =============================================================================
168
169/// Read-only access to the world's current sequence number.
170///
171/// Appears in handler function signatures alongside other params.
172/// Derefs to [`Sequence`].
173///
174/// # Example
175///
176/// ```ignore
177/// use nexus_rt::{Seq, Handler, IntoHandler};
178///
179/// fn log_event(seq: Seq, event: u64) {
180///     println!("event {} at sequence {}", event, seq.get());
181/// }
182/// ```
183#[derive(Clone, Copy)]
184pub struct Seq(pub(crate) Sequence);
185
186impl Seq {
187    /// Returns the current sequence value.
188    #[inline(always)]
189    pub const fn get(&self) -> Sequence {
190        self.0
191    }
192}
193
194impl Deref for Seq {
195    type Target = Sequence;
196
197    #[inline(always)]
198    fn deref(&self) -> &Sequence {
199        &self.0
200    }
201}
202
203/// Mutable access to the world's current sequence number.
204///
205/// Allows handlers to advance the sequence — useful for stamping
206/// outbound messages with monotonic sequence numbers.
207///
208/// # Example
209///
210/// ```ignore
211/// use nexus_rt::{SeqMut, Handler, IntoHandler};
212///
213/// fn send_message(mut seq: SeqMut<'_>, event: u64) {
214///     let msg_seq = seq.advance();
215///     // stamp msg_seq on outbound message
216/// }
217/// ```
218pub struct SeqMut<'w>(pub(crate) &'w Cell<Sequence>);
219
220impl SeqMut<'_> {
221    /// Returns the current sequence value.
222    #[inline(always)]
223    pub fn get(&self) -> Sequence {
224        self.0.get()
225    }
226
227    /// Advance the sequence by 1 and return the new value.
228    #[inline(always)]
229    pub fn advance(&mut self) -> Sequence {
230        let next = Sequence(self.0.get().0.wrapping_add(1));
231        self.0.set(next);
232        next
233    }
234}
235
236// =============================================================================
237// Tests
238// =============================================================================
239
240#[cfg(test)]
241mod tests {
242    use super::*;
243    use crate::world::Resource;
244
245    struct Val(u64);
246    impl Resource for Val {}
247
248    #[test]
249    fn res_deref() {
250        let val = Val(42);
251        let res = Res::new(&val);
252        assert_eq!(res.0, 42);
253    }
254
255    #[test]
256    fn res_mut_deref() {
257        let mut val = Val(0);
258        let mut res = ResMut::new(&mut val);
259        res.0 = 99;
260        assert_eq!(val.0, 99);
261    }
262
263    #[test]
264    fn res_mut_deref_mut_no_stamp() {
265        // ResMut::deref_mut is now a plain pass-through — no stamping.
266        let mut val = Val(0);
267        let mut res = ResMut::new(&mut val);
268        *res = Val(123);
269        assert_eq!(val.0, 123);
270    }
271
272    #[test]
273    fn res_is_copy() {
274        // Compile-time proof that Res<T> is Copy (and Clone) without
275        // requiring T: Copy or T: Clone — Val implements neither.
276        fn assert_copy<U: Copy>(_: U) {}
277        let val = Val(42);
278        let res = Res::new(&val);
279        assert_copy(res);
280        let a = res;
281        let b = res; // Copy — not a move
282        assert_eq!(a.0, 42);
283        assert_eq!(b.0, 42);
284    }
285
286    #[test]
287    fn res_pass_to_inner_function() {
288        // The motivating use case: passing Res<T> to inner functions
289        // without moving.
290        fn inner(r: Res<'_, Val>) -> u64 {
291            r.0
292        }
293        let val = Val(7);
294        let res = Res::new(&val);
295        assert_eq!(inner(res), 7);
296        assert_eq!(inner(res), 7); // would not compile without Copy
297    }
298
299    #[test]
300    fn res_mut_reborrow() {
301        // ResMut::reborrow() lets us pass ResMut<T> (the wrapper) to
302        // inner functions without moving.
303        fn inner(mut r: ResMut<'_, Val>) {
304            r.0 += 1;
305        }
306        let mut val = Val(0);
307        let mut res = ResMut::new(&mut val);
308        inner(res.reborrow());
309        inner(res.reborrow());
310        inner(res.reborrow());
311        // res is usable again here; original lifetime restored.
312        assert_eq!(res.0, 3);
313    }
314
315    #[test]
316    fn res_mut_reborrow_then_use_original() {
317        // After the reborrow goes out of scope, the original is usable
318        // for both shared and mutable access.
319        let mut val = Val(10);
320        let mut res = ResMut::new(&mut val);
321        {
322            let mut rb = res.reborrow();
323            rb.0 = 20;
324        }
325        // Original ResMut usable again.
326        res.0 = 30;
327        assert_eq!(val.0, 30);
328    }
329
330    #[test]
331    fn seq_get() {
332        let seq = Seq(Sequence(42));
333        assert_eq!(seq.get(), Sequence(42));
334    }
335
336    #[test]
337    fn seq_mut_advance() {
338        let cell = Cell::new(Sequence(0));
339        let mut seq = SeqMut(&cell);
340        let next = seq.advance();
341        assert_eq!(next, Sequence(1));
342        assert_eq!(cell.get(), Sequence(1));
343    }
344}