1use std::cell::Cell;
4use std::ops::{Deref, DerefMut};
5
6use crate::world::Sequence;
7
8pub struct Res<'w, T: 'static> {
16 value: &'w T,
17 changed_at: Sequence,
18 current_sequence: Sequence,
19}
20
21impl<'w, T: 'static> Res<'w, T> {
22 pub(crate) fn new(value: &'w T, changed_at: Sequence, current_sequence: Sequence) -> Self {
23 Self {
24 value,
25 changed_at,
26 current_sequence,
27 }
28 }
29
30 pub fn is_changed(&self) -> bool {
32 self.changed_at == self.current_sequence
33 }
34}
35
36impl<T: 'static> Deref for Res<'_, T> {
37 type Target = T;
38
39 #[inline(always)]
40 fn deref(&self) -> &T {
41 self.value
42 }
43}
44
45pub struct ResMut<'w, T: 'static> {
54 value: &'w mut T,
55 changed_at: &'w Cell<Sequence>,
56 current_sequence: Sequence,
57}
58
59impl<'w, T: 'static> ResMut<'w, T> {
60 pub(crate) fn new(
61 value: &'w mut T,
62 changed_at: &'w Cell<Sequence>,
63 current_sequence: Sequence,
64 ) -> Self {
65 Self {
66 value,
67 changed_at,
68 current_sequence,
69 }
70 }
71
72 pub fn is_changed(&self) -> bool {
74 self.changed_at.get() == self.current_sequence
75 }
76}
77
78impl<T: 'static> Deref for ResMut<'_, T> {
79 type Target = T;
80
81 #[inline(always)]
82 fn deref(&self) -> &T {
83 self.value
84 }
85}
86
87impl<T: 'static> DerefMut for ResMut<'_, T> {
88 #[inline(always)]
89 fn deref_mut(&mut self) -> &mut T {
90 self.changed_at.set(self.current_sequence);
91 self.value
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn res_deref() {
101 let val = 42u64;
102 let res = Res::new(&val, Sequence::default(), Sequence::default());
103 assert_eq!(*res, 42);
104 }
105
106 #[test]
107 fn res_is_changed() {
108 let val = 42u64;
109 let tick = Sequence::default();
110 let res = Res::new(&val, tick, tick);
111 assert!(res.is_changed());
112 }
113
114 #[test]
115 fn res_not_changed() {
116 let val = 42u64;
117 let res = Res::new(&val, Sequence::default(), Sequence(1));
119 assert!(!res.is_changed());
120 }
121
122 #[test]
123 fn res_mut_deref_mut() {
124 let mut val = 1u64;
125 let changed_at = Cell::new(Sequence::default());
126 let mut res = ResMut::new(&mut val, &changed_at, Sequence::default());
127 *res = 99;
128 assert_eq!(*res, 99);
129 drop(res);
130 assert_eq!(val, 99);
131 }
132
133 #[test]
134 fn res_mut_deref_mut_stamps() {
135 let mut val = 1u64;
136 let changed_at = Cell::new(Sequence(0));
137 let current = Sequence(5);
138 let mut res = ResMut::new(&mut val, &changed_at, current);
139
140 assert_eq!(changed_at.get(), Sequence(0));
142
143 *res = 99;
144
145 assert_eq!(changed_at.get(), Sequence(5));
147 }
148
149 #[test]
150 fn res_mut_deref_does_not_stamp() {
151 let mut val = 42u64;
152 let changed_at = Cell::new(Sequence(0));
153 let current = Sequence(5);
154 let res = ResMut::new(&mut val, &changed_at, current);
155
156 let _ = *res;
158 assert_eq!(changed_at.get(), Sequence(0));
159 }
160
161 #[test]
162 fn res_mut_is_changed() {
163 let mut val = 1u64;
164 let changed_at = Cell::new(Sequence(3));
165 let res = ResMut::new(&mut val, &changed_at, Sequence(3));
166 assert!(res.is_changed());
167
168 let res2 = ResMut::new(&mut val, &changed_at, Sequence(4));
169 assert!(!res2.is_changed());
170 }
171}