Thanks to visit codestin.com
Credit goes to docs.rs

bevy_ecs/schedule/
node.rs

1use alloc::{boxed::Box, vec::Vec};
2use bevy_utils::prelude::DebugName;
3use core::{
4    any::TypeId,
5    fmt::{self, Debug},
6    ops::{Index, IndexMut, Range},
7};
8
9use bevy_platform::collections::HashMap;
10use slotmap::{new_key_type, Key, KeyData, SecondaryMap, SlotMap};
11
12use crate::{
13    component::{CheckChangeTicks, Tick},
14    prelude::{SystemIn, SystemSet},
15    query::FilteredAccessSet,
16    schedule::{
17        graph::{Direction, GraphNodeId},
18        BoxedCondition, InternedSystemSet,
19    },
20    system::{
21        ReadOnlySystem, RunSystemError, ScheduleSystem, System, SystemParamValidationError,
22        SystemStateFlags,
23    },
24    world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World},
25};
26
27/// A [`SystemWithAccess`] stored in a [`ScheduleGraph`](crate::schedule::ScheduleGraph).
28pub(crate) struct SystemNode {
29    pub(crate) inner: Option<SystemWithAccess>,
30}
31
32/// A [`ScheduleSystem`] stored alongside the access returned from [`System::initialize`].
33pub struct SystemWithAccess {
34    /// The system itself.
35    pub system: ScheduleSystem,
36    /// The access returned by [`System::initialize`].
37    /// This will be empty if the system has not been initialized yet.
38    pub access: FilteredAccessSet,
39}
40
41impl SystemWithAccess {
42    /// Constructs a new [`SystemWithAccess`] from a [`ScheduleSystem`].
43    /// The `access` will initially be empty.
44    pub fn new(system: ScheduleSystem) -> Self {
45        Self {
46            system,
47            access: FilteredAccessSet::new(),
48        }
49    }
50}
51
52impl System for SystemWithAccess {
53    type In = ();
54    type Out = ();
55
56    #[inline]
57    fn name(&self) -> DebugName {
58        self.system.name()
59    }
60
61    #[inline]
62    fn type_id(&self) -> TypeId {
63        self.system.type_id()
64    }
65
66    #[inline]
67    fn flags(&self) -> SystemStateFlags {
68        self.system.flags()
69    }
70
71    #[inline]
72    unsafe fn run_unsafe(
73        &mut self,
74        input: SystemIn<'_, Self>,
75        world: UnsafeWorldCell,
76    ) -> Result<Self::Out, RunSystemError> {
77        // SAFETY: Caller ensures the same safety requirements.
78        unsafe { self.system.run_unsafe(input, world) }
79    }
80
81    #[cfg(feature = "hotpatching")]
82    #[inline]
83    fn refresh_hotpatch(&mut self) {
84        self.system.refresh_hotpatch();
85    }
86
87    #[inline]
88    fn apply_deferred(&mut self, world: &mut World) {
89        self.system.apply_deferred(world);
90    }
91
92    #[inline]
93    fn queue_deferred(&mut self, world: DeferredWorld) {
94        self.system.queue_deferred(world);
95    }
96
97    #[inline]
98    unsafe fn validate_param_unsafe(
99        &mut self,
100        world: UnsafeWorldCell,
101    ) -> Result<(), SystemParamValidationError> {
102        // SAFETY: Caller ensures the same safety requirements.
103        unsafe { self.system.validate_param_unsafe(world) }
104    }
105
106    #[inline]
107    fn initialize(&mut self, world: &mut World) -> FilteredAccessSet {
108        self.system.initialize(world)
109    }
110
111    #[inline]
112    fn check_change_tick(&mut self, check: CheckChangeTicks) {
113        self.system.check_change_tick(check);
114    }
115
116    #[inline]
117    fn default_system_sets(&self) -> Vec<InternedSystemSet> {
118        self.system.default_system_sets()
119    }
120
121    #[inline]
122    fn get_last_run(&self) -> Tick {
123        self.system.get_last_run()
124    }
125
126    #[inline]
127    fn set_last_run(&mut self, last_run: Tick) {
128        self.system.set_last_run(last_run);
129    }
130}
131
132/// A [`BoxedCondition`] stored alongside the access returned from [`System::initialize`].
133pub struct ConditionWithAccess {
134    /// The condition itself.
135    pub condition: BoxedCondition,
136    /// The access returned by [`System::initialize`].
137    /// This will be empty if the system has not been initialized yet.
138    pub access: FilteredAccessSet,
139}
140
141impl ConditionWithAccess {
142    /// Constructs a new [`ConditionWithAccess`] from a [`BoxedCondition`].
143    /// The `access` will initially be empty.
144    pub const fn new(condition: BoxedCondition) -> Self {
145        Self {
146            condition,
147            access: FilteredAccessSet::new(),
148        }
149    }
150}
151
152impl System for ConditionWithAccess {
153    type In = ();
154    type Out = bool;
155
156    #[inline]
157    fn name(&self) -> DebugName {
158        self.condition.name()
159    }
160
161    #[inline]
162    fn type_id(&self) -> TypeId {
163        self.condition.type_id()
164    }
165
166    #[inline]
167    fn flags(&self) -> SystemStateFlags {
168        self.condition.flags()
169    }
170
171    #[inline]
172    unsafe fn run_unsafe(
173        &mut self,
174        input: SystemIn<'_, Self>,
175        world: UnsafeWorldCell,
176    ) -> Result<Self::Out, RunSystemError> {
177        // SAFETY: Caller ensures the same safety requirements.
178        unsafe { self.condition.run_unsafe(input, world) }
179    }
180
181    #[cfg(feature = "hotpatching")]
182    #[inline]
183    fn refresh_hotpatch(&mut self) {
184        self.condition.refresh_hotpatch();
185    }
186
187    #[inline]
188    fn apply_deferred(&mut self, world: &mut World) {
189        self.condition.apply_deferred(world);
190    }
191
192    #[inline]
193    fn queue_deferred(&mut self, world: DeferredWorld) {
194        self.condition.queue_deferred(world);
195    }
196
197    #[inline]
198    unsafe fn validate_param_unsafe(
199        &mut self,
200        world: UnsafeWorldCell,
201    ) -> Result<(), SystemParamValidationError> {
202        // SAFETY: Caller ensures the same safety requirements.
203        unsafe { self.condition.validate_param_unsafe(world) }
204    }
205
206    #[inline]
207    fn initialize(&mut self, world: &mut World) -> FilteredAccessSet {
208        self.condition.initialize(world)
209    }
210
211    #[inline]
212    fn check_change_tick(&mut self, check: CheckChangeTicks) {
213        self.condition.check_change_tick(check);
214    }
215
216    #[inline]
217    fn default_system_sets(&self) -> Vec<InternedSystemSet> {
218        self.condition.default_system_sets()
219    }
220
221    #[inline]
222    fn get_last_run(&self) -> Tick {
223        self.condition.get_last_run()
224    }
225
226    #[inline]
227    fn set_last_run(&mut self, last_run: Tick) {
228        self.condition.set_last_run(last_run);
229    }
230}
231
232impl SystemNode {
233    /// Create a new [`SystemNode`]
234    pub fn new(system: ScheduleSystem) -> Self {
235        Self {
236            inner: Some(SystemWithAccess::new(system)),
237        }
238    }
239
240    /// Obtain a reference to the [`SystemWithAccess`] represented by this node.
241    pub fn get(&self) -> Option<&SystemWithAccess> {
242        self.inner.as_ref()
243    }
244
245    /// Obtain a mutable reference to the [`SystemWithAccess`] represented by this node.
246    pub fn get_mut(&mut self) -> Option<&mut SystemWithAccess> {
247        self.inner.as_mut()
248    }
249}
250
251new_key_type! {
252    /// A unique identifier for a system in a [`ScheduleGraph`].
253    pub struct SystemKey;
254    /// A unique identifier for a system set in a [`ScheduleGraph`].
255    pub struct SystemSetKey;
256}
257
258impl GraphNodeId for SystemKey {
259    type Adjacent = (SystemKey, Direction);
260    type Edge = (SystemKey, SystemKey);
261
262    fn kind(&self) -> &'static str {
263        "system"
264    }
265}
266
267impl GraphNodeId for SystemSetKey {
268    type Adjacent = (SystemSetKey, Direction);
269    type Edge = (SystemSetKey, SystemSetKey);
270
271    fn kind(&self) -> &'static str {
272        "system set"
273    }
274}
275
276impl TryFrom<NodeId> for SystemKey {
277    type Error = SystemSetKey;
278
279    fn try_from(value: NodeId) -> Result<Self, Self::Error> {
280        match value {
281            NodeId::System(key) => Ok(key),
282            NodeId::Set(key) => Err(key),
283        }
284    }
285}
286
287impl TryFrom<NodeId> for SystemSetKey {
288    type Error = SystemKey;
289
290    fn try_from(value: NodeId) -> Result<Self, Self::Error> {
291        match value {
292            NodeId::System(key) => Err(key),
293            NodeId::Set(key) => Ok(key),
294        }
295    }
296}
297
298/// Unique identifier for a system or system set stored in a [`ScheduleGraph`].
299///
300/// [`ScheduleGraph`]: crate::schedule::ScheduleGraph
301#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
302pub enum NodeId {
303    /// Identifier for a system.
304    System(SystemKey),
305    /// Identifier for a system set.
306    Set(SystemSetKey),
307}
308
309impl NodeId {
310    /// Returns `true` if the identified node is a system.
311    pub const fn is_system(&self) -> bool {
312        matches!(self, NodeId::System(_))
313    }
314
315    /// Returns `true` if the identified node is a system set.
316    pub const fn is_set(&self) -> bool {
317        matches!(self, NodeId::Set(_))
318    }
319
320    /// Returns the system key if the node is a system, otherwise `None`.
321    pub const fn as_system(&self) -> Option<SystemKey> {
322        match self {
323            NodeId::System(system) => Some(*system),
324            NodeId::Set(_) => None,
325        }
326    }
327
328    /// Returns the system set key if the node is a system set, otherwise `None`.
329    pub const fn as_set(&self) -> Option<SystemSetKey> {
330        match self {
331            NodeId::System(_) => None,
332            NodeId::Set(set) => Some(*set),
333        }
334    }
335}
336
337impl GraphNodeId for NodeId {
338    type Adjacent = CompactNodeIdAndDirection;
339    type Edge = CompactNodeIdPair;
340
341    fn kind(&self) -> &'static str {
342        match self {
343            NodeId::System(n) => n.kind(),
344            NodeId::Set(n) => n.kind(),
345        }
346    }
347}
348
349impl From<SystemKey> for NodeId {
350    fn from(system: SystemKey) -> Self {
351        NodeId::System(system)
352    }
353}
354
355impl From<SystemSetKey> for NodeId {
356    fn from(set: SystemSetKey) -> Self {
357        NodeId::Set(set)
358    }
359}
360
361/// Compact storage of a [`NodeId`] and a [`Direction`].
362#[derive(Clone, Copy)]
363pub struct CompactNodeIdAndDirection {
364    key: KeyData,
365    is_system: bool,
366    direction: Direction,
367}
368
369impl Debug for CompactNodeIdAndDirection {
370    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371        let tuple: (_, _) = (*self).into();
372        tuple.fmt(f)
373    }
374}
375
376impl From<(NodeId, Direction)> for CompactNodeIdAndDirection {
377    fn from((id, direction): (NodeId, Direction)) -> Self {
378        let key = match id {
379            NodeId::System(key) => key.data(),
380            NodeId::Set(key) => key.data(),
381        };
382        let is_system = id.is_system();
383
384        Self {
385            key,
386            is_system,
387            direction,
388        }
389    }
390}
391
392impl From<CompactNodeIdAndDirection> for (NodeId, Direction) {
393    fn from(value: CompactNodeIdAndDirection) -> Self {
394        let node = match value.is_system {
395            true => NodeId::System(value.key.into()),
396            false => NodeId::Set(value.key.into()),
397        };
398
399        (node, value.direction)
400    }
401}
402
403/// Compact storage of a [`NodeId`] pair.
404#[derive(Clone, Copy, Hash, PartialEq, Eq)]
405pub struct CompactNodeIdPair {
406    key_a: KeyData,
407    key_b: KeyData,
408    is_system_a: bool,
409    is_system_b: bool,
410}
411
412impl Debug for CompactNodeIdPair {
413    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414        let tuple: (_, _) = (*self).into();
415        tuple.fmt(f)
416    }
417}
418
419impl From<(NodeId, NodeId)> for CompactNodeIdPair {
420    fn from((a, b): (NodeId, NodeId)) -> Self {
421        let key_a = match a {
422            NodeId::System(index) => index.data(),
423            NodeId::Set(index) => index.data(),
424        };
425        let is_system_a = a.is_system();
426
427        let key_b = match b {
428            NodeId::System(index) => index.data(),
429            NodeId::Set(index) => index.data(),
430        };
431        let is_system_b = b.is_system();
432
433        Self {
434            key_a,
435            key_b,
436            is_system_a,
437            is_system_b,
438        }
439    }
440}
441
442impl From<CompactNodeIdPair> for (NodeId, NodeId) {
443    fn from(value: CompactNodeIdPair) -> Self {
444        let a = match value.is_system_a {
445            true => NodeId::System(value.key_a.into()),
446            false => NodeId::Set(value.key_a.into()),
447        };
448
449        let b = match value.is_system_b {
450            true => NodeId::System(value.key_b.into()),
451            false => NodeId::Set(value.key_b.into()),
452        };
453
454        (a, b)
455    }
456}
457
458/// Container for systems in a schedule.
459#[derive(Default)]
460pub struct Systems {
461    /// List of systems in the schedule.
462    nodes: SlotMap<SystemKey, SystemNode>,
463    /// List of conditions for each system, in the same order as `nodes`.
464    conditions: SecondaryMap<SystemKey, Vec<ConditionWithAccess>>,
465    /// Systems and their conditions that have not been initialized yet.
466    uninit: Vec<SystemKey>,
467}
468
469impl Systems {
470    /// Returns the number of systems in this container.
471    pub fn len(&self) -> usize {
472        self.nodes.len()
473    }
474
475    /// Returns `true` if this container is empty.
476    pub fn is_empty(&self) -> bool {
477        self.nodes.is_empty()
478    }
479
480    /// Returns a reference to the system with the given key, if it exists.
481    pub fn get(&self, key: SystemKey) -> Option<&SystemWithAccess> {
482        self.nodes.get(key).and_then(|node| node.get())
483    }
484
485    /// Returns a mutable reference to the system with the given key, if it exists.
486    pub fn get_mut(&mut self, key: SystemKey) -> Option<&mut SystemWithAccess> {
487        self.nodes.get_mut(key).and_then(|node| node.get_mut())
488    }
489
490    /// Returns a mutable reference to the system with the given key, panicking
491    /// if it does not exist.
492    ///
493    /// # Panics
494    ///
495    /// If the system with the given key does not exist in this container.
496    pub(crate) fn node_mut(&mut self, key: SystemKey) -> &mut SystemNode {
497        &mut self.nodes[key]
498    }
499
500    /// Returns `true` if the system with the given key has conditions.
501    pub fn has_conditions(&self, key: SystemKey) -> bool {
502        self.conditions
503            .get(key)
504            .is_some_and(|conditions| !conditions.is_empty())
505    }
506
507    /// Returns a reference to the conditions for the system with the given key, if it exists.
508    pub fn get_conditions(&self, key: SystemKey) -> Option<&[ConditionWithAccess]> {
509        self.conditions.get(key).map(Vec::as_slice)
510    }
511
512    /// Returns a mutable reference to the conditions for the system with the given key, if it exists.
513    pub fn get_conditions_mut(&mut self, key: SystemKey) -> Option<&mut Vec<ConditionWithAccess>> {
514        self.conditions.get_mut(key)
515    }
516
517    /// Returns an iterator over all systems and their conditions in this
518    /// container.
519    pub fn iter(
520        &self,
521    ) -> impl Iterator<Item = (SystemKey, &ScheduleSystem, &[ConditionWithAccess])> + '_ {
522        self.nodes.iter().filter_map(|(key, node)| {
523            let system = &node.get()?.system;
524            let conditions = self
525                .conditions
526                .get(key)
527                .map(Vec::as_slice)
528                .unwrap_or_default();
529            Some((key, system, conditions))
530        })
531    }
532
533    /// Inserts a new system into the container, along with its conditions,
534    /// and queues it to be initialized later in [`Systems::initialize`].
535    ///
536    /// We have to defer initialization of systems in the container until we have
537    /// `&mut World` access, so we store these in a list until
538    /// [`Systems::initialize`] is called. This is usually done upon the first
539    /// run of the schedule.
540    pub fn insert(
541        &mut self,
542        system: ScheduleSystem,
543        conditions: Vec<Box<dyn ReadOnlySystem<In = (), Out = bool>>>,
544    ) -> SystemKey {
545        let key = self.nodes.insert(SystemNode::new(system));
546        self.conditions.insert(
547            key,
548            conditions
549                .into_iter()
550                .map(ConditionWithAccess::new)
551                .collect(),
552        );
553        self.uninit.push(key);
554        key
555    }
556
557    /// Returns `true` if all systems in this container have been initialized.
558    pub fn is_initialized(&self) -> bool {
559        self.uninit.is_empty()
560    }
561
562    /// Initializes all systems and their conditions that have not been
563    /// initialized yet.
564    pub fn initialize(&mut self, world: &mut World) {
565        for key in self.uninit.drain(..) {
566            let Some(system) = self.nodes.get_mut(key).and_then(|node| node.get_mut()) else {
567                continue;
568            };
569            system.access = system.system.initialize(world);
570            let Some(conditions) = self.conditions.get_mut(key) else {
571                continue;
572            };
573            for condition in conditions {
574                condition.access = condition.condition.initialize(world);
575            }
576        }
577    }
578}
579
580impl Index<SystemKey> for Systems {
581    type Output = SystemWithAccess;
582
583    #[track_caller]
584    fn index(&self, key: SystemKey) -> &Self::Output {
585        self.get(key)
586            .unwrap_or_else(|| panic!("System with key {:?} does not exist in the schedule", key))
587    }
588}
589
590impl IndexMut<SystemKey> for Systems {
591    #[track_caller]
592    fn index_mut(&mut self, key: SystemKey) -> &mut Self::Output {
593        self.get_mut(key)
594            .unwrap_or_else(|| panic!("System with key {:?} does not exist in the schedule", key))
595    }
596}
597
598/// Container for system sets in a schedule.
599#[derive(Default)]
600pub struct SystemSets {
601    /// List of system sets in the schedule.
602    sets: SlotMap<SystemSetKey, InternedSystemSet>,
603    /// List of conditions for each system set, in the same order as `sets`.
604    conditions: SecondaryMap<SystemSetKey, Vec<ConditionWithAccess>>,
605    /// Map from system sets to their keys.
606    ids: HashMap<InternedSystemSet, SystemSetKey>,
607    /// System sets that have not been initialized yet.
608    uninit: Vec<UninitializedSet>,
609}
610
611/// A system set's conditions that have not been initialized yet.
612struct UninitializedSet {
613    key: SystemSetKey,
614    /// The range of indices in [`SystemSets::conditions`] that correspond
615    /// to conditions that have not been initialized yet.
616    ///
617    /// [`SystemSets::conditions`] for a given set may be appended to
618    /// multiple times (e.g. when `configure_sets` is called multiple with
619    /// the same set), so we need to track which conditions in that list
620    /// are newly added and not yet initialized.
621    ///
622    /// Systems don't need this tracking because each `add_systems` call
623    /// creates separate nodes in the graph with their own conditions,
624    /// so all conditions are initialized together.
625    uninitialized_conditions: Range<usize>,
626}
627
628impl SystemSets {
629    /// Returns the number of system sets in this container.
630    pub fn len(&self) -> usize {
631        self.sets.len()
632    }
633
634    /// Returns `true` if this container is empty.
635    pub fn is_empty(&self) -> bool {
636        self.sets.is_empty()
637    }
638
639    /// Returns `true` if the given set is present in this container.
640    pub fn contains(&self, set: impl SystemSet) -> bool {
641        self.ids.contains_key(&set.intern())
642    }
643
644    /// Returns a reference to the system set with the given key, if it exists.
645    pub fn get(&self, key: SystemSetKey) -> Option<&dyn SystemSet> {
646        self.sets.get(key).map(|set| &**set)
647    }
648
649    /// Returns the key for the given system set, inserting it into this
650    /// container if it does not already exist.
651    pub fn get_key_or_insert(&mut self, set: InternedSystemSet) -> SystemSetKey {
652        *self.ids.entry(set).or_insert_with(|| {
653            let key = self.sets.insert(set);
654            self.conditions.insert(key, Vec::new());
655            key
656        })
657    }
658
659    /// Returns `true` if the system set with the given key has conditions.
660    pub fn has_conditions(&self, key: SystemSetKey) -> bool {
661        self.conditions
662            .get(key)
663            .is_some_and(|conditions| !conditions.is_empty())
664    }
665
666    /// Returns a reference to the conditions for the system set with the given
667    /// key, if it exists.
668    pub fn get_conditions(&self, key: SystemSetKey) -> Option<&[ConditionWithAccess]> {
669        self.conditions.get(key).map(Vec::as_slice)
670    }
671
672    /// Returns a mutable reference to the conditions for the system set with
673    /// the given key, if it exists.
674    pub fn get_conditions_mut(
675        &mut self,
676        key: SystemSetKey,
677    ) -> Option<&mut Vec<ConditionWithAccess>> {
678        self.conditions.get_mut(key)
679    }
680
681    /// Returns an iterator over all system sets in this container, along with
682    /// their conditions.
683    pub fn iter(
684        &self,
685    ) -> impl Iterator<Item = (SystemSetKey, &dyn SystemSet, &[ConditionWithAccess])> {
686        self.sets.iter().filter_map(|(key, set)| {
687            let conditions = self.conditions.get(key)?.as_slice();
688            Some((key, &**set, conditions))
689        })
690    }
691
692    /// Inserts conditions for a system set into the container, and queues the
693    /// newly added conditions to be initialized later in [`SystemSets::initialize`].
694    ///
695    /// If the set was not already present in the container, it is added automatically.
696    ///
697    /// We have to defer initialization of system set conditions in the container
698    /// until we have `&mut World` access, so we store these in a list until
699    /// [`SystemSets::initialize`] is called. This is usually done upon the
700    /// first run of the schedule.
701    pub fn insert(
702        &mut self,
703        set: InternedSystemSet,
704        new_conditions: Vec<Box<dyn ReadOnlySystem<In = (), Out = bool>>>,
705    ) -> SystemSetKey {
706        let key = self.get_key_or_insert(set);
707        if !new_conditions.is_empty() {
708            let current_conditions = &mut self.conditions[key];
709            let start = current_conditions.len();
710            self.uninit.push(UninitializedSet {
711                key,
712                uninitialized_conditions: start..(start + new_conditions.len()),
713            });
714            current_conditions.extend(new_conditions.into_iter().map(ConditionWithAccess::new));
715        }
716        key
717    }
718
719    /// Returns `true` if all system sets' conditions in this container have
720    /// been initialized.
721    pub fn is_initialized(&self) -> bool {
722        self.uninit.is_empty()
723    }
724
725    /// Initializes all system sets' conditions that have not been
726    /// initialized yet. Because a system set's conditions may be appended to
727    /// multiple times, we track which conditions were added since the last
728    /// initialization and only initialize those.
729    pub fn initialize(&mut self, world: &mut World) {
730        for uninit in self.uninit.drain(..) {
731            let Some(conditions) = self.conditions.get_mut(uninit.key) else {
732                continue;
733            };
734            for condition in &mut conditions[uninit.uninitialized_conditions] {
735                condition.access = condition.initialize(world);
736            }
737        }
738    }
739}
740
741impl Index<SystemSetKey> for SystemSets {
742    type Output = dyn SystemSet;
743
744    #[track_caller]
745    fn index(&self, key: SystemSetKey) -> &Self::Output {
746        self.get(key).unwrap_or_else(|| {
747            panic!(
748                "System set with key {:?} does not exist in the schedule",
749                key
750            )
751        })
752    }
753}
754
755#[cfg(test)]
756mod tests {
757    use alloc::{boxed::Box, vec};
758
759    use crate::{
760        prelude::SystemSet,
761        schedule::{SystemSets, Systems},
762        system::IntoSystem,
763        world::World,
764    };
765
766    #[derive(SystemSet, Clone, Copy, PartialEq, Eq, Debug, Hash)]
767    pub struct TestSet;
768
769    #[test]
770    fn systems() {
771        fn empty_system() {}
772
773        let mut systems = Systems::default();
774        assert!(systems.is_empty());
775        assert_eq!(systems.len(), 0);
776
777        let system = Box::new(IntoSystem::into_system(empty_system));
778        let key = systems.insert(system, vec![]);
779
780        assert!(!systems.is_empty());
781        assert_eq!(systems.len(), 1);
782        assert!(systems.get(key).is_some());
783        assert!(systems.get_conditions(key).is_some());
784        assert!(systems.get_conditions(key).unwrap().is_empty());
785        assert!(systems.get_mut(key).is_some());
786        assert!(!systems.is_initialized());
787        assert!(systems.iter().next().is_some());
788
789        let mut world = World::new();
790        systems.initialize(&mut world);
791        assert!(systems.is_initialized());
792    }
793
794    #[test]
795    fn system_sets() {
796        fn always_true() -> bool {
797            true
798        }
799
800        let mut sets = SystemSets::default();
801        assert!(sets.is_empty());
802        assert_eq!(sets.len(), 0);
803
804        let condition = Box::new(IntoSystem::into_system(always_true));
805        let key = sets.insert(TestSet.intern(), vec![condition]);
806
807        assert!(!sets.is_empty());
808        assert_eq!(sets.len(), 1);
809        assert!(sets.get(key).is_some());
810        assert!(sets.get_conditions(key).is_some());
811        assert!(!sets.get_conditions(key).unwrap().is_empty());
812        assert!(!sets.is_initialized());
813        assert!(sets.iter().next().is_some());
814
815        let mut world = World::new();
816        sets.initialize(&mut world);
817        assert!(sets.is_initialized());
818    }
819}