1use alloc::boxed::Box;
2use core::{
3 any::TypeId,
4 fmt::Debug,
5 hash::{Hash, Hasher},
6 marker::PhantomData,
7};
8
9pub use crate::label::DynEq;
10pub use bevy_ecs_macros::{ScheduleLabel, SystemSet};
11
12use crate::{
13 define_label,
14 intern::Interned,
15 system::{
16 ExclusiveFunctionSystem, ExclusiveSystemParamFunction, FunctionSystem,
17 IsExclusiveFunctionSystem, IsFunctionSystem, SystemParamFunction,
18 },
19};
20
21define_label!(
22 #[diagnostic::on_unimplemented(
24 note = "consider annotating `{Self}` with `#[derive(ScheduleLabel)]`"
25 )]
26 ScheduleLabel,
27 SCHEDULE_LABEL_INTERNER
28);
29
30define_label!(
31 #[diagnostic::on_unimplemented(
33 note = "consider annotating `{Self}` with `#[derive(SystemSet)]`"
34 )]
35 SystemSet,
36 SYSTEM_SET_INTERNER,
37 extra_methods: {
38 fn system_type(&self) -> Option<TypeId> {
40 None
41 }
42
43 fn is_anonymous(&self) -> bool {
45 false
46 }
47 },
48 extra_methods_impl: {
49 fn system_type(&self) -> Option<TypeId> {
50 (**self).system_type()
51 }
52
53 fn is_anonymous(&self) -> bool {
54 (**self).is_anonymous()
55 }
56 }
57);
58
59pub type InternedSystemSet = Interned<dyn SystemSet>;
61pub type InternedScheduleLabel = Interned<dyn ScheduleLabel>;
63
64pub struct SystemTypeSet<T: 'static>(PhantomData<fn() -> T>);
71
72impl<T: 'static> SystemTypeSet<T> {
73 pub(crate) fn new() -> Self {
74 Self(PhantomData)
75 }
76}
77
78impl<T> Debug for SystemTypeSet<T> {
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 f.debug_tuple("SystemTypeSet")
81 .field(&format_args!("fn {}()", &core::any::type_name::<T>()))
82 .finish()
83 }
84}
85
86impl<T> Hash for SystemTypeSet<T> {
87 fn hash<H: Hasher>(&self, _state: &mut H) {
88 }
90}
91
92impl<T> Clone for SystemTypeSet<T> {
93 fn clone(&self) -> Self {
94 *self
95 }
96}
97
98impl<T> Copy for SystemTypeSet<T> {}
99
100impl<T> PartialEq for SystemTypeSet<T> {
101 #[inline]
102 fn eq(&self, _other: &Self) -> bool {
103 true
105 }
106}
107
108impl<T> Eq for SystemTypeSet<T> {}
109
110impl<T> SystemSet for SystemTypeSet<T> {
111 fn system_type(&self) -> Option<TypeId> {
112 Some(TypeId::of::<T>())
113 }
114
115 fn dyn_clone(&self) -> Box<dyn SystemSet> {
116 Box::new(*self)
117 }
118
119 fn as_dyn_eq(&self) -> &dyn DynEq {
120 self
121 }
122
123 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
124 TypeId::of::<Self>().hash(&mut state);
125 self.hash(&mut state);
126 }
127}
128
129#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
133pub struct AnonymousSet(usize);
134
135impl AnonymousSet {
136 pub(crate) fn new(id: usize) -> Self {
137 Self(id)
138 }
139}
140
141impl SystemSet for AnonymousSet {
142 fn is_anonymous(&self) -> bool {
143 true
144 }
145
146 fn dyn_clone(&self) -> Box<dyn SystemSet> {
147 Box::new(*self)
148 }
149
150 fn as_dyn_eq(&self) -> &dyn DynEq {
151 self
152 }
153
154 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
155 TypeId::of::<Self>().hash(&mut state);
156 self.hash(&mut state);
157 }
158}
159
160#[diagnostic::on_unimplemented(
168 message = "`{Self}` is not a system set",
169 label = "invalid system set"
170)]
171pub trait IntoSystemSet<Marker>: Sized {
172 type Set: SystemSet;
174
175 fn into_system_set(self) -> Self::Set;
177}
178
179impl<S: SystemSet> IntoSystemSet<()> for S {
181 type Set = Self;
182
183 #[inline]
184 fn into_system_set(self) -> Self::Set {
185 self
186 }
187}
188
189impl<Marker, F> IntoSystemSet<(IsFunctionSystem, Marker)> for F
191where
192 Marker: 'static,
193 F: SystemParamFunction<Marker>,
194{
195 type Set = SystemTypeSet<FunctionSystem<Marker, F>>;
196
197 #[inline]
198 fn into_system_set(self) -> Self::Set {
199 SystemTypeSet::<FunctionSystem<Marker, F>>::new()
200 }
201}
202
203impl<Marker, F> IntoSystemSet<(IsExclusiveFunctionSystem, Marker)> for F
205where
206 Marker: 'static,
207 F: ExclusiveSystemParamFunction<Marker>,
208{
209 type Set = SystemTypeSet<ExclusiveFunctionSystem<Marker, F>>;
210
211 #[inline]
212 fn into_system_set(self) -> Self::Set {
213 SystemTypeSet::<ExclusiveFunctionSystem<Marker, F>>::new()
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use crate::{
220 resource::Resource,
221 schedule::{tests::ResMut, Schedule},
222 };
223
224 use super::*;
225
226 #[test]
227 fn test_schedule_label() {
228 use crate::world::World;
229
230 #[derive(Resource)]
231 struct Flag(bool);
232
233 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
234 struct A;
235
236 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
237 struct B;
238
239 let mut world = World::new();
240
241 let mut schedule = Schedule::new(A);
242 schedule.add_systems(|mut flag: ResMut<Flag>| flag.0 = true);
243 world.add_schedule(schedule);
244
245 let interned = A.intern();
246
247 world.insert_resource(Flag(false));
248 world.run_schedule(interned);
249 assert!(world.resource::<Flag>().0);
250
251 world.insert_resource(Flag(false));
252 world.run_schedule(interned);
253 assert!(world.resource::<Flag>().0);
254
255 assert_ne!(A.intern(), B.intern());
256 }
257
258 #[test]
259 fn test_derive_schedule_label() {
260 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
261 struct UnitLabel;
262
263 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
264 struct TupleLabel(u32, u32);
265
266 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
267 struct StructLabel {
268 a: u32,
269 b: u32,
270 }
271
272 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
273 struct EmptyTupleLabel();
274
275 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
276 struct EmptyStructLabel {}
277
278 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
279 enum EnumLabel {
280 #[default]
281 Unit,
282 Tuple(u32, u32),
283 Struct {
284 a: u32,
285 b: u32,
286 },
287 }
288
289 #[derive(ScheduleLabel, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
290 struct GenericLabel<T>(PhantomData<T>);
291
292 assert_eq!(UnitLabel.intern(), UnitLabel.intern());
293 assert_eq!(EnumLabel::Unit.intern(), EnumLabel::Unit.intern());
294 assert_ne!(UnitLabel.intern(), EnumLabel::Unit.intern());
295 assert_ne!(UnitLabel.intern(), TupleLabel(0, 0).intern());
296 assert_ne!(EnumLabel::Unit.intern(), EnumLabel::Tuple(0, 0).intern());
297
298 assert_eq!(TupleLabel(0, 0).intern(), TupleLabel(0, 0).intern());
299 assert_eq!(
300 EnumLabel::Tuple(0, 0).intern(),
301 EnumLabel::Tuple(0, 0).intern()
302 );
303 assert_ne!(TupleLabel(0, 0).intern(), TupleLabel(0, 1).intern());
304 assert_ne!(
305 EnumLabel::Tuple(0, 0).intern(),
306 EnumLabel::Tuple(0, 1).intern()
307 );
308 assert_ne!(TupleLabel(0, 0).intern(), EnumLabel::Tuple(0, 0).intern());
309 assert_ne!(
310 TupleLabel(0, 0).intern(),
311 StructLabel { a: 0, b: 0 }.intern()
312 );
313 assert_ne!(
314 EnumLabel::Tuple(0, 0).intern(),
315 EnumLabel::Struct { a: 0, b: 0 }.intern()
316 );
317
318 assert_eq!(
319 StructLabel { a: 0, b: 0 }.intern(),
320 StructLabel { a: 0, b: 0 }.intern()
321 );
322 assert_eq!(
323 EnumLabel::Struct { a: 0, b: 0 }.intern(),
324 EnumLabel::Struct { a: 0, b: 0 }.intern()
325 );
326 assert_ne!(
327 StructLabel { a: 0, b: 0 }.intern(),
328 StructLabel { a: 0, b: 1 }.intern()
329 );
330 assert_ne!(
331 EnumLabel::Struct { a: 0, b: 0 }.intern(),
332 EnumLabel::Struct { a: 0, b: 1 }.intern()
333 );
334 assert_ne!(
335 StructLabel { a: 0, b: 0 }.intern(),
336 EnumLabel::Struct { a: 0, b: 0 }.intern()
337 );
338 assert_ne!(
339 StructLabel { a: 0, b: 0 }.intern(),
340 EnumLabel::Struct { a: 0, b: 0 }.intern()
341 );
342 assert_ne!(StructLabel { a: 0, b: 0 }.intern(), UnitLabel.intern(),);
343 assert_ne!(
344 EnumLabel::Struct { a: 0, b: 0 }.intern(),
345 EnumLabel::Unit.intern()
346 );
347
348 assert_eq!(
349 GenericLabel::<u32>(PhantomData).intern(),
350 GenericLabel::<u32>(PhantomData).intern()
351 );
352 assert_ne!(
353 GenericLabel::<u32>(PhantomData).intern(),
354 GenericLabel::<u64>(PhantomData).intern()
355 );
356 }
357
358 #[test]
359 fn test_derive_system_set() {
360 #[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
361 struct UnitSet;
362
363 #[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
364 struct TupleSet(u32, u32);
365
366 #[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
367 struct StructSet {
368 a: u32,
369 b: u32,
370 }
371
372 #[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
373 struct EmptyTupleSet();
374
375 #[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
376 struct EmptyStructSet {}
377
378 #[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
379 enum EnumSet {
380 #[default]
381 Unit,
382 Tuple(u32, u32),
383 Struct {
384 a: u32,
385 b: u32,
386 },
387 }
388
389 #[derive(SystemSet, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
390 struct GenericSet<T>(PhantomData<T>);
391
392 assert_eq!(UnitSet.intern(), UnitSet.intern());
393 assert_eq!(EnumSet::Unit.intern(), EnumSet::Unit.intern());
394 assert_ne!(UnitSet.intern(), EnumSet::Unit.intern());
395 assert_ne!(UnitSet.intern(), TupleSet(0, 0).intern());
396 assert_ne!(EnumSet::Unit.intern(), EnumSet::Tuple(0, 0).intern());
397
398 assert_eq!(TupleSet(0, 0).intern(), TupleSet(0, 0).intern());
399 assert_eq!(EnumSet::Tuple(0, 0).intern(), EnumSet::Tuple(0, 0).intern());
400 assert_ne!(TupleSet(0, 0).intern(), TupleSet(0, 1).intern());
401 assert_ne!(EnumSet::Tuple(0, 0).intern(), EnumSet::Tuple(0, 1).intern());
402 assert_ne!(TupleSet(0, 0).intern(), EnumSet::Tuple(0, 0).intern());
403 assert_ne!(TupleSet(0, 0).intern(), StructSet { a: 0, b: 0 }.intern());
404 assert_ne!(
405 EnumSet::Tuple(0, 0).intern(),
406 EnumSet::Struct { a: 0, b: 0 }.intern()
407 );
408
409 assert_eq!(
410 StructSet { a: 0, b: 0 }.intern(),
411 StructSet { a: 0, b: 0 }.intern()
412 );
413 assert_eq!(
414 EnumSet::Struct { a: 0, b: 0 }.intern(),
415 EnumSet::Struct { a: 0, b: 0 }.intern()
416 );
417 assert_ne!(
418 StructSet { a: 0, b: 0 }.intern(),
419 StructSet { a: 0, b: 1 }.intern()
420 );
421 assert_ne!(
422 EnumSet::Struct { a: 0, b: 0 }.intern(),
423 EnumSet::Struct { a: 0, b: 1 }.intern()
424 );
425 assert_ne!(
426 StructSet { a: 0, b: 0 }.intern(),
427 EnumSet::Struct { a: 0, b: 0 }.intern()
428 );
429 assert_ne!(
430 StructSet { a: 0, b: 0 }.intern(),
431 EnumSet::Struct { a: 0, b: 0 }.intern()
432 );
433 assert_ne!(StructSet { a: 0, b: 0 }.intern(), UnitSet.intern(),);
434 assert_ne!(
435 EnumSet::Struct { a: 0, b: 0 }.intern(),
436 EnumSet::Unit.intern()
437 );
438
439 assert_eq!(
440 GenericSet::<u32>(PhantomData).intern(),
441 GenericSet::<u32>(PhantomData).intern()
442 );
443 assert_ne!(
444 GenericSet::<u32>(PhantomData).intern(),
445 GenericSet::<u64>(PhantomData).intern()
446 );
447 }
448}