my_ecs/ecs/sys/
system.rs

1use super::{
2    query::{EntQueryMut, Query, QueryMut, ResQuery, ResQueryMut},
3    request::{
4        Request, RequestInfo, RequestKey, Response, StoreRequestInfo, SystemBuffer, RINFO_STOR,
5    },
6};
7use crate::{
8    ds::{ATypeId, ListPos, ManagedMutPtr, NonNullExt, SetList, SimpleVecPool},
9    ecs::EcsError,
10    util::{macros::debug_format, Or},
11};
12use std::{
13    any::{self, Any},
14    borrow,
15    collections::{HashMap, HashSet},
16    fmt,
17    hash::{self, BuildHasher},
18    marker::PhantomData,
19    mem,
20    ops::{Deref, DerefMut},
21    ptr::NonNull,
22    sync::Arc,
23};
24
25use SystemState::*;
26
27/// System is a type that accesses components, entities, or resoruces.
28///
29/// [`Fn`], [`FnMut`], and [`FnOnce`] with certain parameters implement this
30/// trait by the crate. Of course `struct` also can implement this trait. It's
31/// useful when you need some data for a system.
32///
33/// # Examples
34///
35/// Here's an example of system declaration.
36/// ```
37/// # use my_ecs::prelude::*;
38///
39/// #[derive(Component)] struct Ca;
40/// #[derive(Component)] struct Cb;
41/// #[derive(Component)] struct Cc;
42/// #[derive(Component)] struct Cd;
43/// #[derive(Resource)] struct Ra(i32);
44/// #[derive(Resource)] struct Rb(i32);
45/// #[derive(Resource)] struct Rc(i32);
46/// #[derive(Resource)] struct Rd(i32);
47///
48/// filter!(Fa, Target = Ca); // All, Any, None are ommited for simplicity.
49/// filter!(Fb, Target = Cb);
50/// filter!(Fc, Target = Cc);
51/// filter!(Fd, Target = Cd);
52/// filter!(Fe, All = (Ca, Cb)); // Any and None are ommited for simplicity.
53/// filter!(Ff, All = (Cc, Cd)); // Any and None are ommited for simplicity.
54///
55/// // Function system declaration.
56///
57/// fn system_a(
58///     r: Read<(Fa, Fb)>, // Read request for the filters.
59///     w: Write<(Fc, Fd)>, // Write request for the filters.
60///     rr: ResRead<(Ra, Rb)>, // Read request for the resources.
61///     rw: ResWrite<(Rc, Rd)>, // Write request for the resources.
62///     ew: EntWrite<(Fe, Ff)>, // Write request for the filters.
63/// ) { /* ... */ }
64///
65/// // Struct system declaration.
66///
67/// request!(Req,
68///     Read = (Fa, Fb),
69///     Write = (Fc, Fd),
70///     ResRead = (Ra, Rb),
71///     ResWrite = (Rc, Rd),
72///     EntWrite = (Fe, Ff)
73/// );
74///
75/// struct SystemB;
76///
77/// impl System for SystemB {
78///     type Request = Req;
79///     fn run(&mut self, resp: Response<'_, Self::Request>) { /* ... */ }
80/// }
81/// ```
82///
83/// ---
84///
85/// This is another example to show how to add systems to an ECS instance.
86/// ```
87/// use my_ecs::prelude::*;
88///
89/// // Systems do nothing for simplicity.
90///
91/// struct StructSystem {
92///     data: String,
93/// }
94///
95/// impl System for StructSystem {
96///     type Request = ();
97///     fn run(&mut self, resp: Response<'_, Self::Request>) { /* ... */ }
98/// }
99///
100/// let struct_system = StructSystem { data: "".to_owned() };
101/// let fn_system = || {};
102/// let s: String = "".to_owned();
103/// let fn_once_system = move || { drop(s); };
104///
105/// Ecs::default(WorkerPool::new(), [])
106///     .add_systems((struct_system, fn_system))
107///     .add_once_system(fn_once_system)
108///     .unwrap();
109/// ```
110//
111// Clients can define their systems with some data. And we're going to send
112// those systems to other workers, so it's good to add `Send` bound to the trait
113// for safety.
114#[allow(private_interfaces, private_bounds)]
115pub trait System: Send + 'static {
116    type Request: Request;
117
118    /// Runs the system with the response corresponding to its request.
119    fn run(&mut self, resp: Response<'_, Self::Request>);
120
121    #[doc(hidden)]
122    #[allow(unused_variables)]
123    fn run_private(&mut self, sid: SystemId, buf: ManagedMutPtr<SystemBuffer>) {}
124
125    /// Does a certain behavior on transitions of system state.
126    ///
127    /// See [`SystemState`] for more details.
128    #[allow(unused_variables)]
129    fn on_transition(&mut self, from: SystemState, to: SystemState) {}
130
131    /// Returns system name.
132    fn name() -> &'static str {
133        any::type_name::<Self>()
134    }
135
136    #[doc(hidden)]
137    fn key() -> SystemKey {
138        SystemKey::of::<Self>()
139    }
140
141    #[doc(hidden)]
142    fn into_data(self) -> SystemData
143    where
144        Self: Sized + 'static,
145    {
146        let boxed = Box::new(self);
147        // Safety: Infallible.
148        let ptr = unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) };
149        Self::_create_data(ptr, SystemFlags::OWNED_SET)
150    }
151
152    #[doc(hidden)]
153    unsafe fn create_data(ptr: NonNull<dyn Invoke + Send>) -> SystemData
154    where
155        Self: Sized + 'static,
156    {
157        Self::_create_data(ptr, SystemFlags::OWNED_RESET)
158    }
159
160    #[doc(hidden)]
161    fn _create_data(invoker: NonNull<dyn Invoke + Send>, flags: SystemFlags) -> SystemData {
162        let mut stor = RINFO_STOR.lock().unwrap();
163        let rinfo = Arc::clone(Self::Request::get_info_from(&mut *stor));
164        drop(stor);
165
166        SystemData {
167            id: SystemId::dummy(),
168            flags,
169            invoker,
170            info: Arc::new(SystemInfo::new(
171                Self::name(),
172                Self::key(),
173                Self::Request::key(),
174                rinfo,
175            )),
176        }
177    }
178}
179
180/// A system group that will be invoked together in a cycle by scheduler.
181///
182/// Systems can be in one of states such as [`Active`], [`Inactive`], [`Dead`],
183/// and [`Poisoned`].
184///
185/// Possible system transitions are as follows,
186///
187/// | From         | To           | Methods                                  |
188/// | ---          | ---          | ---                                      |
189/// |              | [`Inactive`] | [`register`]                             |
190/// | [`Inactive`] | [`Active`]   | [`activate`]                             |
191/// | [`Inactive`] | [`Dead`]     | [`unregister`]                           |
192/// | [`Inactive`] | [`Poisoned`] | [`poison`]                               |
193/// | [`Active`]   | [`Inactive`] | [`inactivate`], [`tick`] w\ non-volatile |
194/// | [`Active`]   | [`Dead`]     | [`tick`] w\ volatile                     |
195/// | [`Active`]   | [`Poisoned`] | [`poison`]                               |
196/// | [`Dead`]     |              | [`drain_dead`]                           |
197/// | [`Poisoned`] |              | [`drain_poisoned`]                       |
198///
199/// [`register`]: Self::register
200/// [`activate`]: Self::activate
201/// [`inactivate`]: Self::inactivate
202/// [`poison`]: Self::poison
203/// [`unregister`]: Self::unregister
204/// [`tick`]: Self::tick
205/// [`drain_dead`]: Self::drain_dead
206/// [`drain_poisoned`]: Self::drain_poisoned
207#[derive(Debug)]
208pub(crate) struct SystemGroup<S> {
209    /// System id that will be given to new registered system.
210    cur_id: SystemId,
211
212    /// Active state systems.
213    active: SystemCycle<S>,
214
215    /// Inactive state systems.
216    inactive: HashSet<SystemData, S>,
217
218    /// Dead state systems.
219    dead: Vec<SystemData>,
220
221    /// Poisoned state systems.
222    poisoned: Vec<PoisonedSystem>,
223
224    /// Volatile systems will be removed permanently instead of moving to inactive list.
225    /// For instance, setup system and FnOnce system are volatile.
226    volatile: HashSet<SystemId, S>,
227
228    /// Active system's lifetime.
229    lifetime: SystemLifetime<S>,
230}
231
232impl<S> SystemGroup<S>
233where
234    S: BuildHasher + Default,
235{
236    pub(crate) fn new(gi: u16) -> Self {
237        let dummy = ().into_data();
238
239        Self {
240            cur_id: SystemId::new(gi, 1),
241            active: SystemCycle::new(dummy),
242            inactive: HashSet::default(),
243            dead: Vec::new(),
244            poisoned: Vec::new(),
245            volatile: HashSet::default(),
246            lifetime: SystemLifetime::new(),
247        }
248    }
249
250    /// Clears all stored systems.
251    ///
252    /// Systems will be removed through state transitions.
253    /// - [`Active`] -> [`Inactive`] -> [`Dead`] -> Removed
254    /// - [`Poisoned`] -> Removed
255    ///
256    /// Which means their [`on_transition`] will be called in order.
257    ///
258    /// [`on_transition`]: System::on_transition
259    pub(crate) fn clear(&mut self) {
260        // Active -> Inactive or Dead
261        let mut sids = Vec::with_capacity(self.len_active() + self.len_inactive());
262        for sdata in self.active.values() {
263            sids.push(sdata.id());
264        }
265        while let Some(sid) = sids.pop() {
266            self.inactivate(&sid).unwrap();
267        }
268
269        // Inactive -> Dead
270        for sdata in self.inactive.iter() {
271            sids.push(sdata.id());
272        }
273        while let Some(sid) = sids.pop() {
274            self.unregister(&sid).unwrap();
275        }
276
277        // Clears Dead & Poisoned.
278        self.drain_dead();
279        self.drain_poisoned();
280    }
281
282    pub(crate) fn len_active(&self) -> usize {
283        self.active.len()
284    }
285
286    pub(crate) fn len_inactive(&self) -> usize {
287        self.inactive.len()
288    }
289
290    // TODO: rename
291    pub(crate) fn get_active_mut(&mut self) -> &mut SystemCycle<S> {
292        &mut self.active
293    }
294
295    pub(crate) fn is_active(&self, sid: &SystemId) -> bool {
296        self.active.contains(sid)
297    }
298
299    /// Determines whether a system for the given id is in [`Active`] or
300    /// [`Inactive`] states.
301    pub(crate) fn contains(&self, sid: &SystemId) -> bool {
302        self.contains_active(sid) || self.contains_inactive(sid)
303    }
304
305    /// Determines whether a system for the given id is in [`Active`] state.
306    pub(crate) fn contains_active(&self, sid: &SystemId) -> bool {
307        self.active.contains(sid)
308    }
309
310    /// Determines whether a system for the given id is in [`Inactive`] state.
311    pub(crate) fn contains_inactive(&self, sid: &SystemId) -> bool {
312        self.inactive.contains(sid)
313    }
314
315    /// Looks for a system for the given id in [`Active`] systems.
316    pub(crate) fn get_active(&self, sid: &SystemId) -> Option<&SystemData> {
317        self.active.get(sid)
318    }
319
320    /// Returns system id that the next registered system will have.
321    pub(crate) fn next_system_id(&self) -> SystemId {
322        self.cur_id
323    }
324
325    /// Registers a system.
326    ///
327    /// If there's no error during registration, the system state becomes
328    /// [`Inactive`].
329    ///
330    /// Cases below are considered error.
331    /// - System id is not correct. System id must be the same as the one
332    ///   [`Self::next_system_id`] returns.
333    /// - Found a system that has the same system id in [`Active`] or `Inactive`
334    ///   systems.
335    //
336    // It can be possible to set system id here, but then, system data may
337    // contain invalid system id for a second. That's not what we want, so you
338    // must set the correct id by calling [`Self::next_system_id`] beforehand.
339    pub(crate) fn register(
340        &mut self,
341        sdata: SystemData,
342        volatile: bool,
343    ) -> Result<(), EcsError<SystemData>> {
344        // Validates.
345        if sdata.id() != self.cur_id {
346            let reason = debug_format!("invalid system id");
347            return Err(EcsError::Unknown(reason, sdata));
348        }
349        if self.contains(&sdata.id()) {
350            let reason = debug_format!("duplicated system id");
351            return Err(EcsError::Unknown(reason, sdata));
352        }
353
354        // Increases system id for the next one.
355        let sid = sdata.id();
356        self.cur_id.add_system_index(1);
357
358        // Inserts the system into inactive list.
359        let is_new = self.inactive.insert(sdata);
360        debug_assert!(is_new);
361
362        // We need to record whether the system is volatile or not.
363        if volatile {
364            let is_new = self.volatile.insert(sid);
365            debug_assert!(is_new);
366        }
367        Ok(())
368    }
369
370    /// Activates a system for the given id.
371    ///
372    /// Cases below are considered ok.
373    /// - No error
374    ///
375    /// Then the system state transitions from [`Inactive`] to [`Active`].
376    ///
377    /// Whereas cases below are considered error.
378    /// - If the system was not in `Inactive` state.
379    /// - If insert position pointed to a particular system, and the system was
380    ///   not in `Active` states.
381    pub(crate) fn activate(
382        &mut self,
383        target: &SystemId,
384        at: InsertPos,
385        live: Tick,
386    ) -> Result<(), EcsError> {
387        // Validates.
388        if let InsertPos::After(after) = at {
389            if !self.is_active(&after) {
390                // Unknown `after` system.
391                let reason =
392                    debug_format!("cannot activate a system due to invalid insert position");
393                return Err(EcsError::UnknownSystem(reason, ()));
394            }
395        }
396
397        if let Some(mut sdata) = self.inactive.take(target) {
398            debug_assert_eq!(sdata.id(), *target);
399
400            sdata.as_invoker_mut().on_transition(Inactive, Active);
401            let must_true = self.active.insert(sdata, at);
402            debug_assert!(must_true);
403
404            // Inserts system id into lifetime manager.
405            self.lifetime.register(*target, live);
406            Ok(())
407        } else {
408            let reason = debug_format!("system activation is allowed for inactive systems only");
409            Err(EcsError::UnknownSystem(reason, ()))
410        }
411    }
412
413    /// Unregisters a system for the given id.
414    ///
415    /// Cases below are considered ok.
416    /// - If the system was already in [`Dead`] state.
417    /// - No error
418    ///
419    /// Then the system state transitions from [`Inactive`] to `Dead`.
420    ///
421    /// But if the system was not in `Inactive` state, returns error.
422    pub(crate) fn unregister(&mut self, sid: &SystemId) -> Result<(), EcsError> {
423        if let Some(mut sdata) = self.inactive.take(sid) {
424            sdata.as_invoker_mut().on_transition(Inactive, Dead);
425            self.dead.push(sdata);
426            Ok(())
427        } else {
428            let reason = debug_format!("tried to unregister a not inactive system");
429            Err(EcsError::UnknownSystem(reason, ()))
430        }
431    }
432
433    /// Moves a system for the given id to [`Poisoned`] state.
434    ///
435    /// If the system was in one of [`Active`] or [`Inactive`] states, the
436    /// system state transitions to `Poisoned` state. Otherwise, just returns
437    /// given payload back.
438    pub(crate) fn poison(
439        &mut self,
440        sid: &SystemId,
441        payload: Box<dyn Any + Send>,
442    ) -> Result<(), EcsError<Box<dyn Any + Send>>> {
443        let sdata = if let Some(mut sdata) = self.active.remove(sid) {
444            sdata.as_invoker_mut().on_transition(Active, Poisoned);
445            sdata
446        } else if let Some(mut sdata) = self.inactive.take(sid) {
447            sdata.as_invoker_mut().on_transition(Inactive, Poisoned);
448            sdata
449        } else {
450            let reason = debug_format!("tried to poison a not (in)active system");
451            return Err(EcsError::UnknownSystem(reason, payload));
452        };
453        let poisoned = PoisonedSystem::from_system_data(sdata, payload);
454        self.poisoned.push(poisoned);
455        Ok(())
456    }
457
458    /// Inactivates a system for the given id.
459    ///
460    /// If inactivation is successful, system state changes depends on system
461    /// volatility as shown below.
462    /// - If the system is volatile, it changes to [`Dead`] state.
463    /// - Otherwise, it changes to [`Inactive`] state.
464    ///
465    /// Cases below are considered ok.
466    /// - If the system was already in `Inactive` state.
467    /// - No error
468    ///
469    /// Then the system state transitions from `Active` to `Inactive`.
470    ///
471    /// But if the system was not in [`Active`] state, returns error.
472    pub(crate) fn inactivate(&mut self, sid: &SystemId) -> Result<(), EcsError> {
473        let Self {
474            active,
475            inactive,
476            dead,
477            volatile,
478            ..
479        } = self;
480
481        Self::_inactivate(sid, active, inactive, dead, volatile)
482    }
483
484    fn _inactivate(
485        sid: &SystemId,
486        active: &mut SystemCycle<S>,
487        inactive: &mut HashSet<SystemData, S>,
488        dead: &mut Vec<SystemData>,
489        volatile: &mut HashSet<SystemId, S>,
490    ) -> Result<(), EcsError> {
491        if inactive.contains(sid) {
492            Ok(())
493        } else if let Some(mut sdata) = active.remove(sid) {
494            if volatile.contains(sid) {
495                sdata.as_invoker_mut().on_transition(Active, Dead);
496                dead.push(sdata);
497            } else {
498                sdata.as_invoker_mut().on_transition(Active, Inactive);
499                inactive.insert(sdata);
500            }
501            Ok(())
502        } else {
503            let reason = debug_format!("tried to inactivate a not (in)active system");
504            Err(EcsError::UnknownSystem(reason, ()))
505        }
506    }
507
508    /// Removes the whole systems in [`Dead`] state.
509    pub(crate) fn drain_dead(&mut self) -> std::vec::Drain<'_, SystemData> {
510        for sdata in self.dead.iter() {
511            self.volatile.remove(&sdata.id());
512        }
513        self.dead.drain(..)
514    }
515
516    /// Removes the whole systems in [`Poisoned`] state.
517    pub(crate) fn drain_poisoned(&mut self) -> std::vec::Drain<'_, PoisonedSystem> {
518        for poisoned in self.poisoned.iter() {
519            self.volatile.remove(&poisoned.id());
520        }
521        self.poisoned.drain(..)
522    }
523
524    pub(crate) fn tick(&mut self) {
525        let Self {
526            active,
527            inactive,
528            dead,
529            volatile,
530            lifetime,
531            ..
532        } = self;
533
534        if let Some(expired_sids) = lifetime.tick() {
535            while let Some(sid) = expired_sids.pop() {
536                let _ = Self::_inactivate(&sid, active, inactive, dead, volatile);
537            }
538        }
539    }
540}
541
542/// State of a system.
543///
544/// * Active - The system can be run.
545/// * Inactive - The system cannot be run, but it can be reactivated.
546/// * Dead - The system has been completely consumed. It cannot be reactivated.
547/// * Poisoned - The system has panicked. It cannot be reactivated.
548///
549/// System state transitions are as follows.
550///
551/// | From         | To           | Input action                          |
552/// | ---          | ---          | ---                                   |
553/// |              | [`Inactive`] | A system is registered                |
554/// | [`Inactive`] | [`Active`]   | A system is activated                 |
555/// | [`Inactive`] | [`Dead`]     | A system is unregistered              |
556/// | [`Inactive`] | [`Poisoned`] | Not allowed                           |
557/// | [`Active`]   | [`Inactive`] | A system is inactivated or expired    |
558/// | [`Active`]   | [`Dead`]     | A system is expired and it's volatile |
559/// | [`Active`]   | [`Poisoned`] | A system panicked                     |
560/// | [`Dead`]     |              | A system is removed by client         |
561/// | [`Poisoned`] |              | A system is removed by client         |
562#[derive(Debug)]
563pub enum SystemState {
564    Active,
565    Inactive,
566    Dead,
567    Poisoned,
568}
569
570/// Currently activated systems.
571#[derive(Debug)]
572#[repr(transparent)]
573pub(crate) struct SystemCycle<S>(SetList<SystemId, SystemData, S>);
574
575impl<S> SystemCycle<S>
576where
577    S: BuildHasher + Default,
578{
579    // `SetList` requires default head node, just makes empty system and puts it in.
580    pub(crate) fn new(dummy: SystemData) -> Self {
581        Self(SetList::new(dummy))
582    }
583
584    pub(crate) fn len(&self) -> usize {
585        self.0.len()
586    }
587
588    pub(crate) fn contains(&self, sid: &SystemId) -> bool {
589        self.0.contains_key(sid)
590    }
591
592    pub(crate) fn insert(&mut self, sdata: SystemData, at: InsertPos) -> bool {
593        match at {
594            InsertPos::After(after) => self.0.insert(sdata.id(), sdata, &after),
595            InsertPos::Back => self.0.push_back(sdata.id(), sdata),
596            InsertPos::Front => self.0.push_front(sdata.id(), sdata),
597        }
598    }
599
600    pub(crate) fn remove(&mut self, sid: &SystemId) -> Option<SystemData> {
601        self.0.remove(sid)
602    }
603
604    pub(crate) fn iter_begin(&mut self) -> SystemCycleIter<'_, S> {
605        SystemCycleIter::new(&mut self.0)
606    }
607}
608
609impl<S> Deref for SystemCycle<S> {
610    type Target = SetList<SystemId, SystemData, S>;
611
612    fn deref(&self) -> &Self::Target {
613        &self.0
614    }
615}
616
617impl<S> DerefMut for SystemCycle<S> {
618    fn deref_mut(&mut self) -> &mut Self::Target {
619        &mut self.0
620    }
621}
622
623#[derive(Debug)]
624#[repr(transparent)]
625pub(crate) struct SystemCycleIter<'a, S> {
626    raw: RawSystemCycleIter<S>,
627
628    _marker: PhantomData<&'a mut ()>,
629}
630
631impl<S> SystemCycleIter<'_, S> {
632    pub(crate) fn into_raw(self) -> RawSystemCycleIter<S> {
633        self.raw
634    }
635
636    pub(crate) unsafe fn from_raw(raw: RawSystemCycleIter<S>) -> Self {
637        Self {
638            raw,
639            _marker: PhantomData,
640        }
641    }
642
643    /// Returns current system position.
644    pub(crate) fn position(&self) -> ListPos {
645        self.raw.position()
646    }
647}
648
649impl<'a, S> SystemCycleIter<'a, S>
650where
651    S: BuildHasher,
652{
653    pub(crate) fn new(systems: &'a mut SetList<SystemId, SystemData, S>) -> Self {
654        Self {
655            raw: RawSystemCycleIter::new(systems),
656            _marker: PhantomData,
657        }
658    }
659
660    /// Returns system to be run this time.
661    pub(crate) fn get(&mut self) -> Option<&mut SystemData> {
662        // Safety: We're actually borrowing `raw.systems`.
663        unsafe { self.raw.get() }
664    }
665
666    /// Returns system at the given position.
667    pub(crate) fn get_at(&mut self, pos: ListPos) -> Option<&mut SystemData> {
668        // Safety: We're actually borrowing `raw.systems`.
669        unsafe { self.raw.get_at(pos) }
670    }
671}
672
673#[derive(Debug)]
674pub(crate) struct RawSystemCycleIter<S> {
675    /// Currently activated systems.
676    systems: NonNull<SetList<SystemId, SystemData, S>>,
677
678    /// System position to be run.
679    cur_pos: ListPos,
680}
681
682impl<S> RawSystemCycleIter<S> {
683    /// Returns current system position.
684    pub(crate) fn position(&self) -> ListPos {
685        self.cur_pos
686    }
687}
688
689impl<S> RawSystemCycleIter<S>
690where
691    S: BuildHasher,
692{
693    pub(crate) fn new(systems: &mut SetList<SystemId, SystemData, S>) -> Self {
694        let cur_pos = systems.first_position();
695        // Safety: Infallible.
696        let systems = unsafe { NonNull::new_unchecked(systems as *mut _) };
697
698        Self { systems, cur_pos }
699    }
700
701    /// Moves system position on to the next.
702    pub(crate) unsafe fn next(&mut self) {
703        let systems = unsafe { self.systems.as_ref() };
704        if let Some((next, _sdata)) = systems.iter_next(self.cur_pos) {
705            self.cur_pos = next;
706        }
707    }
708
709    /// Returns system to be run this time.
710    pub(crate) unsafe fn get(&mut self) -> Option<&mut SystemData> {
711        unsafe { self.get_at(self.cur_pos) }
712    }
713
714    /// Returns system at the given position.
715    pub(crate) unsafe fn get_at(&mut self, pos: ListPos) -> Option<&mut SystemData> {
716        let systems = unsafe { self.systems.as_mut() };
717        systems.iter_next_mut(pos).map(|(_, sdata)| sdata)
718    }
719}
720
721impl<S> Clone for RawSystemCycleIter<S> {
722    fn clone(&self) -> Self {
723        *self
724    }
725}
726
727impl<S> Copy for RawSystemCycleIter<S> {}
728
729/// A position to insert a system into system scheduling list.
730///
731/// * Front - Inserts a system to the beginning of the system scheduling list.
732///   The system will be run first on the next scheduling.
733/// * Back - Inserts a system to the end of the system scheduling list. The
734///   system will be run last on the next scheduling.
735/// * After - Inserts a system after a specific system in the system scheduling
736///   list. The system will be run after the designated system.
737#[derive(Debug, Clone, Copy)]
738pub enum InsertPos {
739    Back,
740    Front,
741    After(SystemId),
742}
743
744#[derive(Debug)]
745struct SystemLifetime<S> {
746    /// Monotonically increasing count.
747    tick: Tick,
748
749    /// [`Tick`] -> An index to [`Self::pool`].
750    lives: HashMap<Tick, usize, S>,
751
752    /// Vector contains system ids to be dead at a specific time.
753    pool: SimpleVecPool<SystemId>,
754}
755
756impl<S> SystemLifetime<S>
757where
758    S: BuildHasher + Default,
759{
760    fn new() -> Self {
761        Self {
762            tick: 0,
763            lives: HashMap::default(),
764            pool: SimpleVecPool::new(),
765        }
766    }
767
768    fn register(&mut self, sid: SystemId, live: Tick) {
769        debug_assert!(live > 0);
770
771        let end = self.tick.saturating_add(live);
772        let index = *self.lives.entry(end).or_insert(self.pool.request());
773        let vec = self.pool.get(index);
774        vec.push(sid);
775    }
776
777    fn tick(&mut self) -> Option<&mut Vec<SystemId>> {
778        self.tick += 1;
779        self.lives.remove(&self.tick).map(|index| {
780            self.pool.release(index);
781            self.pool.get(index)
782        })
783    }
784}
785
786/// Empty system.
787impl System for () {
788    type Request = ();
789    fn run(&mut self, _resp: Response<Self::Request>) {}
790}
791
792/// Unique identifier for a type implementing [`System`].
793pub(crate) type SystemKey = ATypeId<SystemKey_>;
794pub(crate) struct SystemKey_;
795
796/// Unique system identifier consisting of group index and system index.
797#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
798pub struct SystemId {
799    group_index: u16,
800    system_index: u16,
801}
802
803impl SystemId {
804    const DUMMY: Self = Self {
805        group_index: u16::MAX,
806        system_index: u16::MAX,
807    };
808    const MAX: u16 = u16::MAX - 1;
809
810    pub(crate) const fn dummy() -> Self {
811        Self::DUMMY
812    }
813
814    pub(crate) fn is_dummy(&self) -> bool {
815        self == &Self::dummy()
816    }
817
818    pub(crate) const fn new(group_index: u16, system_index: u16) -> Self {
819        Self {
820            group_index,
821            system_index,
822        }
823    }
824
825    pub(crate) const fn group_index(&self) -> u16 {
826        self.group_index
827    }
828
829    pub(crate) const fn max_system_index() -> u16 {
830        Self::MAX
831    }
832
833    pub(crate) fn add_system_index(&mut self, by: u16) {
834        assert!(
835            self.system_index < Self::max_system_index(),
836            "number of systems exceeded its limit {}",
837            Self::max_system_index() - 1
838        );
839        self.system_index += by;
840    }
841}
842
843impl Default for SystemId {
844    fn default() -> Self {
845        Self::dummy()
846    }
847}
848
849impl fmt::Display for SystemId {
850    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
851        write!(f, "({}, {})", self.group_index, self.system_index)
852    }
853}
854
855/// # Safety
856///
857/// This struct is commonly managed by scheduler which guarantees valid access
858/// in terms of [`Send`] and [`Sync`] even if it contains raw pointers in it.
859/// But if clients use this struct on their own purposes, they must keep that in
860/// mind.
861pub(crate) struct SystemData {
862    /// Unique id for a system.
863    id: SystemId,
864
865    flags: SystemFlags,
866
867    /// System data and its entry point.
868    invoker: NonNull<(dyn Invoke + Send)>,
869
870    /// Infrequently accessed information such as system's name or request.
871    //
872    // * Why Arc
873    // - In order to share `SystemInfo` with others.
874    // - In order to reduce size of the struct. We move whole `SystemData` when
875    // we activate or inactivate systems.
876    info: Arc<SystemInfo>,
877}
878
879// Safety:
880// - Scheduler controls that a system data is accessed by one worker at a time.
881// - Scheduler provides synchronization over workers accessing the system data.
882// - Where the scheduler doesn't work, clients must access it carefully.
883// - Which means system data is looked like Rust primitive types from its users.
884unsafe impl Send for SystemData {}
885unsafe impl Sync for SystemData {}
886
887impl SystemData {
888    pub(crate) fn try_into_any(self) -> Result<Box<dyn Any + Send>, Self> {
889        if self.flags.is_owned() {
890            // Safety: Checked.
891            let boxed = unsafe { Box::from_raw(self.invoker.as_ptr()) };
892
893            // We don't call drop.
894            mem::forget(self);
895
896            Ok(boxed.into_any())
897        } else {
898            Err(self)
899        }
900    }
901}
902
903impl Drop for SystemData {
904    fn drop(&mut self) {
905        // If this data owns `invoker`, deallocates it.
906        if self.flags.is_owned() {
907            // Safety: Checked.
908            unsafe { drop(Box::from_raw(self.invoker.as_ptr())) };
909        }
910    }
911}
912
913impl fmt::Debug for SystemData {
914    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
915        f.debug_struct("SystemData")
916            .field("id", &self.id)
917            .field("flags", &self.flags)
918            .field("info", &self.info)
919            .finish_non_exhaustive()
920    }
921}
922
923impl hash::Hash for SystemData {
924    fn hash<H: hash::Hasher>(&self, state: &mut H) {
925        self.id.hash(state);
926    }
927}
928
929impl PartialEq for SystemData {
930    fn eq(&self, other: &Self) -> bool {
931        self.id == other.id
932    }
933}
934
935impl Eq for SystemData {}
936
937impl borrow::Borrow<SystemId> for SystemData {
938    fn borrow(&self) -> &SystemId {
939        &self.id
940    }
941}
942
943impl SystemData {
944    pub(crate) const fn id(&self) -> SystemId {
945        self.id
946    }
947
948    pub(crate) const fn flags(&self) -> SystemFlags {
949        self.flags
950    }
951
952    pub(crate) fn set_id(&mut self, sid: SystemId) {
953        self.id = sid;
954    }
955
956    pub(crate) fn union_flags(&mut self, sflags: SystemFlags) {
957        self.flags |= sflags;
958    }
959
960    pub(crate) fn info(&self) -> Arc<SystemInfo> {
961        Arc::clone(&self.info)
962    }
963
964    pub(crate) fn get_request_info(&self) -> &Arc<RequestInfo> {
965        // Safety: It's always Some. See comments of the field.
966        unsafe { self.info.rinfo.as_ref().unwrap_unchecked() }
967    }
968
969    pub(crate) fn as_invoker_mut(&mut self) -> &mut (dyn Invoke + Send) {
970        // Safety: Pointer to invoker is valid to access because
971        // - If `sdata` owns it, we can safely access it.
972        // - If `sdata` doesn't own it, real owner guarantees that.
973        unsafe { self.invoker.as_mut() }
974    }
975
976    pub(crate) unsafe fn task_ptr(&mut self) -> ManagedMutPtr<dyn Invoke + Send> {
977        unsafe {
978            let ptr = self.invoker.as_ptr();
979            let ptr = NonNullExt::new_unchecked(ptr);
980            ManagedMutPtr::new(ptr)
981        }
982    }
983}
984
985#[derive(Debug)]
986pub struct PoisonedSystem {
987    id: SystemId,
988    name: &'static str,
989    data: Option<Box<dyn Any + Send>>,
990    err_payload: Box<dyn Any + Send>,
991}
992
993impl PoisonedSystem {
994    const fn new(
995        id: SystemId,
996        name: &'static str,
997        data: Option<Box<dyn Any + Send>>,
998        err_payload: Box<dyn Any + Send>,
999    ) -> Self {
1000        Self {
1001            id,
1002            name,
1003            data,
1004            err_payload,
1005        }
1006    }
1007
1008    fn from_system_data(sdata: SystemData, err_payload: Box<dyn Any + Send>) -> Self {
1009        let id = sdata.id;
1010        let name = sdata.info().name;
1011        let data = sdata.try_into_any().ok();
1012        Self::new(id, name, data, err_payload)
1013    }
1014
1015    pub fn id(&self) -> SystemId {
1016        self.id
1017    }
1018
1019    pub fn name(&self) -> &'static str {
1020        self.name
1021    }
1022
1023    pub fn take_data(&mut self) -> Option<Box<dyn Any + Send>> {
1024        self.data.take()
1025    }
1026
1027    pub fn into_error_payload(self) -> Box<dyn Any + Send> {
1028        self.err_payload
1029    }
1030}
1031
1032#[derive(Clone, Copy)]
1033pub(crate) struct SystemFlags(u32);
1034
1035bitflags::bitflags! {
1036    impl SystemFlags: u32 {
1037        const DEDI_SET = 1;
1038        const DEDI_RESET = 1 << 1;
1039
1040        const PRIVATE_SET = 1 << 2;
1041        const PRIVATE_RESET = 1 << 3;
1042
1043        const OWNED_SET = 1 << 4;
1044        const OWNED_RESET = 1 << 5;
1045    }
1046}
1047
1048impl SystemFlags {
1049    pub(crate) const fn is_dedi(&self) -> bool {
1050        debug_assert!(!self.is_dedi_empty());
1051
1052        self.intersects(Self::DEDI_SET)
1053    }
1054
1055    pub(crate) const fn is_dedi_empty(&self) -> bool {
1056        !self.intersects(Self::DEDI_SET.union(Self::DEDI_RESET))
1057    }
1058
1059    pub(crate) const fn is_private(&self) -> bool {
1060        debug_assert!(!self.is_private_empty());
1061
1062        self.intersects(Self::PRIVATE_SET)
1063    }
1064
1065    pub(crate) const fn is_private_empty(&self) -> bool {
1066        !self.intersects(Self::PRIVATE_SET.union(Self::PRIVATE_RESET))
1067    }
1068
1069    pub(crate) const fn is_owned(&self) -> bool {
1070        debug_assert!(!self.is_owned_empty());
1071
1072        self.intersects(Self::OWNED_SET)
1073    }
1074
1075    pub(crate) const fn is_owned_empty(&self) -> bool {
1076        !self.intersects(Self::OWNED_SET.union(Self::OWNED_RESET))
1077    }
1078}
1079
1080impl fmt::Debug for SystemFlags {
1081    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1082        let dedi = if !self.is_dedi_empty() {
1083            if self.is_dedi() {
1084                "DEDI"
1085            } else {
1086                "NON-DEDI"
1087            }
1088        } else {
1089            "DEDI?"
1090        };
1091
1092        let private = if !self.is_private_empty() {
1093            if self.is_private() {
1094                "PRIVATE"
1095            } else {
1096                "NON-PRIVATE"
1097            }
1098        } else {
1099            "PRIVATE?"
1100        };
1101
1102        let owned = if !self.is_owned_empty() {
1103            if self.is_owned() {
1104                "OWNED"
1105            } else {
1106                "NON-OWNED"
1107            }
1108        } else {
1109            "OWNED?"
1110        };
1111
1112        f.debug_tuple("SystemFlags")
1113            .field(&[dedi, private, owned].join(" | "))
1114            .finish()
1115    }
1116}
1117
1118pub(crate) struct SystemInfo {
1119    /// System name basically determined by [`any::type_name`].
1120    name: &'static str,
1121
1122    _skey: SystemKey,
1123
1124    /// [`System`] is related to a [`RequestInfo`].
1125    /// This field is the key for the `RequestInfo`.
1126    rkey: RequestKey,
1127
1128    /// [`System`] is related to a [`RequestInfo`].
1129    //
1130    // It's always Some except in drop().
1131    // In drop(), inner type will be dropped first.
1132    rinfo: Option<Arc<RequestInfo>>,
1133}
1134
1135impl SystemInfo {
1136    const fn new(
1137        name: &'static str,
1138        skey: SystemKey,
1139        rkey: RequestKey,
1140        rinfo: Arc<RequestInfo>,
1141    ) -> Self {
1142        Self {
1143            name,
1144            _skey: skey,
1145            rkey,
1146            rinfo: Some(rinfo),
1147        }
1148    }
1149
1150    pub(crate) fn get_request_info(&self) -> &RequestInfo {
1151        // Safety: `self.rinfo` is Some except in drop().
1152        unsafe { self.rinfo.as_ref().unwrap_unchecked() }
1153    }
1154}
1155
1156impl fmt::Debug for SystemInfo {
1157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1158        f.debug_struct("SystemInfo")
1159            .field("name", &self.name)
1160            .finish_non_exhaustive()
1161    }
1162}
1163
1164impl Drop for SystemInfo {
1165    fn drop(&mut self) {
1166        // Self-unregister.
1167        drop(self.rinfo.take());
1168        let mut stor = RINFO_STOR.lock().unwrap();
1169        stor.remove(&self.rkey);
1170    }
1171}
1172
1173/// A descriptor for a [`System`].
1174pub struct SystemDesc<Sys> {
1175    /// System itself. Clients cannot put `SystemData` in, which is only allowed
1176    /// to the crate.
1177    pub(crate) sys: Or<Sys, SystemData>,
1178
1179    /// Whether the system is private system or not. Private system is a kind of
1180    /// systems which is used internally.
1181    pub(crate) private: bool,
1182
1183    /// Group index of the system.
1184    pub group_index: u16,
1185
1186    /// Whether the system is volatile or not. A volatile system will be
1187    /// discarded from memory after get executed as much as its lifetime.
1188    /// Unlike volatile system, non-volatile system will move to inactivate
1189    /// state instead of being discarded.
1190    pub volatile: bool,
1191
1192    /// Lifetime and insert position in an active system cycle.
1193    /// - Lifetime(live): Determines how long the system should be executed.
1194    ///   Whenever client schedules ecs, lifetime of executed system decreases
1195    ///   by 1 conceptually. Zero lifetime is considered inactivation.
1196    /// - Insert position: Active systems get executed in an order. Client can
1197    ///   designate where the system locates. [`InsertPos::Front`] means the
1198    ///   first position in the order, while [`InsertPos::Back`] means the last
1199    ///   position in the order. Of course, client can put the system in the
1200    ///   middle of the order by [`InsertPos::After`].
1201    pub activation: (Tick, InsertPos),
1202}
1203
1204impl<Sys> fmt::Debug for SystemDesc<Sys> {
1205    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1206        f.debug_struct("SystemDesc")
1207            .field("private", &self.private)
1208            .field("group_index", &self.group_index)
1209            .field("volatile", &self.volatile)
1210            .field("activation", &self.activation)
1211            .finish_non_exhaustive()
1212    }
1213}
1214
1215impl<Sys> SystemDesc<Sys>
1216where
1217    Sys: System,
1218{
1219    pub fn with_system<T, OutSys>(self, sys: T) -> SystemDesc<OutSys>
1220    where
1221        T: Into<SystemBond<OutSys>>,
1222        OutSys: System,
1223    {
1224        let sys: SystemBond<OutSys> = sys.into();
1225
1226        SystemDesc::<OutSys> {
1227            sys: Or::A(sys.into_inner()),
1228            private: self.private,
1229            group_index: self.group_index,
1230            volatile: self.volatile,
1231            activation: self.activation,
1232        }
1233    }
1234
1235    pub fn with_once<T, Req, F>(self, sys: T) -> SystemDesc<FnOnceSystem<Req, F>>
1236    where
1237        T: Into<FnOnceSystem<Req, F>>,
1238        FnOnceSystem<Req, F>: System,
1239    {
1240        let activation = if self.activation.0 > 0 {
1241            (1, self.activation.1)
1242        } else {
1243            self.activation
1244        };
1245
1246        SystemDesc::<FnOnceSystem<Req, F>> {
1247            sys: Or::A(sys.into()),
1248            private: self.private,
1249            group_index: self.group_index,
1250            volatile: self.volatile,
1251            activation,
1252        }
1253    }
1254
1255    pub fn with_group_index(self, index: u16) -> Self {
1256        Self {
1257            group_index: index,
1258            ..self
1259        }
1260    }
1261
1262    pub fn with_volatile(self, volatile: bool) -> Self {
1263        Self { volatile, ..self }
1264    }
1265
1266    pub fn with_activation(self, live: Tick, insert_at: InsertPos) -> Self {
1267        Self {
1268            activation: (live, insert_at),
1269            ..self
1270        }
1271    }
1272
1273    // Clients are only able to put in systems, not system data.
1274    pub fn take_system(self) -> Sys {
1275        match self.sys {
1276            Or::A(sys) => sys,
1277            Or::B(_sdata) => panic!(),
1278        }
1279    }
1280
1281    pub(crate) fn with_data(self, sdata: SystemData) -> SystemDesc<()> {
1282        SystemDesc::<()> {
1283            sys: Or::B(sdata),
1284            private: self.private,
1285            group_index: self.group_index,
1286            volatile: self.volatile,
1287            activation: self.activation,
1288        }
1289    }
1290
1291    pub(crate) fn with_private(self, private: bool) -> Self {
1292        Self { private, ..self }
1293    }
1294}
1295
1296impl SystemDesc<()> {
1297    pub const fn new() -> Self {
1298        Self {
1299            sys: Or::A(()),
1300            private: false,
1301            group_index: 0,
1302            volatile: true,
1303            activation: (Tick::MAX, InsertPos::Back),
1304        }
1305    }
1306}
1307
1308impl Default for SystemDesc<()> {
1309    fn default() -> Self {
1310        Self::new()
1311    }
1312}
1313
1314impl<T: System> From<T> for SystemDesc<T> {
1315    fn from(value: T) -> Self {
1316        SystemDesc::new().with_system(value)
1317    }
1318}
1319
1320/// Object safe trait for the [`System`].
1321pub(crate) trait Invoke {
1322    fn invoke(&mut self, buf: &mut SystemBuffer);
1323    fn invoke_private(&mut self, sid: SystemId, buf: ManagedMutPtr<SystemBuffer>);
1324    fn on_transition(&mut self, from: SystemState, to: SystemState);
1325    fn into_any(self: Box<Self>) -> Box<dyn Any + Send>;
1326}
1327
1328impl<S: System> Invoke for S {
1329    fn invoke(&mut self, buf: &mut SystemBuffer) {
1330        self.run(Response::new(buf));
1331    }
1332
1333    fn invoke_private(&mut self, sid: SystemId, buf: ManagedMutPtr<SystemBuffer>) {
1334        self.run_private(sid, buf);
1335    }
1336
1337    fn on_transition(&mut self, from: SystemState, to: SystemState) {
1338        self.on_transition(from, to);
1339    }
1340
1341    fn into_any(self: Box<Self>) -> Box<dyn Any + Send> {
1342        self
1343    }
1344}
1345
1346/// A system that is [`FnMut`].
1347///
1348/// The purpose of this type is to remove boilerplate code related to system
1349/// declaration when clients make systems using functions. Unlike types like
1350/// `struct` or `enum`, functions have parameters which explains what types the
1351/// functions need. The crate exploits the information then makes boilerplate
1352/// code for clients.
1353///
1354/// Plus, there is [`FnOnceSystem`] for [`FnOnce`].
1355///
1356/// * Req - Arbitrary length of parameters of `F`.
1357/// * F - Function.
1358#[repr(transparent)]
1359pub struct FnSystem<Req, F> {
1360    run: F,
1361    _marker: PhantomData<Req>,
1362}
1363
1364unsafe impl<Req, F: Send> Send for FnSystem<Req, F> {}
1365
1366impl<Req, F> fmt::Debug for FnSystem<Req, F>
1367where
1368    Self: System,
1369{
1370    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1371        write!(f, "{}", Self::name())
1372    }
1373}
1374
1375/// A system that is [`FnOnce`].
1376///
1377/// The purpose of this type is to remove boilerplate code related to system
1378/// declaration when clients make systems using functions. Unlike types like
1379/// `struct` or `enum`, functions have parameters which explains what types the
1380/// functions need. The crate exploits the information then makes boilerplate
1381/// code for clients.
1382///
1383/// Plus, there is [`FnSystem`] for [`FnMut`].
1384///
1385/// * Req - Arbitrary length of parameters of `F`.
1386/// * F - Function.
1387#[repr(transparent)]
1388pub struct FnOnceSystem<Req, F> {
1389    run: Option<F>,
1390    _marker: PhantomData<Req>,
1391}
1392
1393unsafe impl<Req, F: Send> Send for FnOnceSystem<Req, F> {}
1394
1395impl<Req, F> fmt::Debug for FnOnceSystem<Req, F>
1396where
1397    Self: System,
1398{
1399    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1400        write!(f, "{}", Self::name())
1401    }
1402}
1403
1404/// Placeholder for implementation of [`FnSystem`] and [`FnOnceSystem`].
1405///
1406/// This is only used internally.
1407//
1408// This helps us avoid implementation conflicts.
1409#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1410pub struct Ph;
1411
1412#[rustfmt::skip]
1413mod impl_for_fn_system {
1414    use super::*;
1415    use crate::ecs::sys::query::{Read, Write, ResRead, ResWrite, EntWrite};
1416
1417    macro_rules! _impl {
1418        (
1419            $req_with_placeholder:ty,
1420            $req_with_tuple:ty
1421            $(,r=$r:ident)?
1422            $(,w=$w:ident)?
1423            $(,rr=$rr:ident)?
1424            $(,rw=$rw:ident)?
1425            $(,ew=$ew:ident)?
1426        ) => {
1427            // FnMut(..) -> FnSystem<..>
1428            impl<F $(,$r)? $(,$w)? $(,$rr)? $(,$rw)? $(,$ew)?>
1429                From<F> for
1430                FnSystem<$req_with_placeholder, F>
1431            where
1432                F: FnMut(
1433                    $(Read<$r>,)?
1434                    $(Write<$w>,)?
1435                    $(ResRead<$rr>,)?
1436                    $(ResWrite<$rw>,)?
1437                    $(EntWrite<$ew>,)?
1438                ),
1439                $($r: Query,)?
1440                $($w: QueryMut,)?
1441                $($rr: ResQuery,)?
1442                $($rw: ResQueryMut,)?
1443                $($ew: EntQueryMut,)?
1444            {
1445                fn from(value: F) -> Self {
1446                    Self {
1447                        run: value,
1448                        _marker: PhantomData,
1449                    }
1450                }
1451            }
1452
1453            // FnOnce(..) -> FnOnceSystem<..>
1454            impl<F $(,$r)? $(,$w)? $(,$rr)? $(,$rw)? $(,$ew)?>
1455                From<F> for
1456                FnOnceSystem<$req_with_placeholder, F>
1457            where
1458                F: FnOnce(
1459                    $(Read<$r>,)?
1460                    $(Write<$w>,)?
1461                    $(ResRead<$rr>,)?
1462                    $(ResWrite<$rw>,)?
1463                    $(EntWrite<$ew>,)?
1464                ),
1465                $($r: Query,)?
1466                $($w: QueryMut,)?
1467                $($rr: ResQuery,)?
1468                $($rw: ResQueryMut,)?
1469                $($ew: EntQueryMut,)?
1470            {
1471                fn from(value: F) -> Self {
1472                    Self {
1473                        run: Some(value),
1474                        _marker: PhantomData,
1475                    }
1476                }
1477            }
1478
1479            // System for FnSystem<..>
1480            impl<F $(,$r)? $(,$w)? $(,$rr)? $(,$rw)? $(,$ew)?>
1481                System for
1482                FnSystem<$req_with_placeholder, F>
1483            where
1484                F: FnMut(
1485                    $(Read<$r>,)?
1486                    $(Write<$w>,)?
1487                    $(ResRead<$rr>,)?
1488                    $(ResWrite<$rw>,)?
1489                    $(EntWrite<$ew>,)?
1490                ) + Send + 'static,
1491                $($r: Query,)?
1492                $($w: QueryMut,)?
1493                $($rr: ResQuery,)?
1494                $($rw: ResQueryMut,)?
1495                $($ew: EntQueryMut,)?
1496            {
1497                type Request = $req_with_tuple;
1498
1499                fn run(&mut self, _resp: Response<Self::Request>) {
1500                    (self.run)(
1501                        $(Read::<'_, $r>(_resp.read),)?
1502                        $(Write::<'_, $w>(_resp.write),)?
1503                        $(ResRead::<'_, $rr>(_resp.res_read),)?
1504                        $(ResWrite::<'_, $rw>(_resp.res_write),)?
1505                        $(EntWrite::<$ew>(_resp.ent_write),)?
1506                    )
1507                }
1508
1509                fn name() -> &'static str {
1510                    std::any::type_name::<F>()
1511                }
1512            }
1513
1514            // System for FnOnceSystem<..>
1515            impl<F $(,$r)? $(,$w)? $(,$rr)? $(,$rw)? $(,$ew)?>
1516                System for
1517                FnOnceSystem<$req_with_placeholder, F>
1518            where
1519                F: FnOnce(
1520                    $(Read<$r>,)?
1521                    $(Write<$w>,)?
1522                    $(ResRead<$rr>,)?
1523                    $(ResWrite<$rw>,)?
1524                    $(EntWrite<$ew>,)?
1525                ) + Send + 'static,
1526                $($r: Query,)?
1527                $($w: QueryMut,)?
1528                $($rr: ResQuery,)?
1529                $($rw: ResQueryMut,)?
1530                $($ew: EntQueryMut,)?
1531            {
1532                type Request = $req_with_tuple;
1533
1534                fn run(&mut self, _resp: Response<Self::Request>) {
1535                    if let Some(run) = self.run.take() {
1536                        (run)(
1537                            $(Read::<'_, $r>(_resp.read),)?
1538                            $(Write::<'_, $w>(_resp.write),)?
1539                            $(ResRead::<'_, $rr>(_resp.res_read),)?
1540                            $(ResWrite::<'_, $rw>(_resp.res_write),)?
1541                            $(EntWrite::<$ew>(_resp.ent_write),)?
1542                        )
1543                    } else {
1544                        panic!(
1545                            "unable to call `{}` twice, which implements FnOnce",
1546                            std::any::type_name::<F>()
1547                        );
1548                    }
1549                }
1550
1551                fn name() -> &'static str {
1552                    std::any::type_name::<F>()
1553                }
1554            }
1555
1556            // FnMut<..> -> SystemBond<..>
1557            impl<F $(,$r)? $(,$w)? $(,$rr)? $(,$rw)? $(,$ew)?>
1558                From<F> for
1559                SystemBond<FnSystem<$req_with_placeholder, F>>
1560            where
1561                F: FnMut(
1562                    $(Read<$r>,)?
1563                    $(Write<$w>,)?
1564                    $(ResRead<$rr>,)?
1565                    $(ResWrite<$rw>,)?
1566                    $(EntWrite<$ew>,)?
1567                ),
1568                $($r: Query,)?
1569                $($w: QueryMut,)?
1570                $($rr: ResQuery,)?
1571                $($rw: ResQueryMut,)?
1572                $($ew: EntQueryMut,)?
1573            {
1574                fn from(value: F) -> Self {
1575                    Self(value.into())
1576                }
1577            }
1578
1579            // FnMut<..> -> SystemDesc<..>
1580            impl<F $(,$r)? $(,$w)? $(,$rr)? $(,$rw)? $(,$ew)?>
1581                From<F> for
1582                SystemDesc<FnSystem<$req_with_placeholder, F>>
1583            where
1584                F: FnMut(
1585                    $(Read<$r>,)?
1586                    $(Write<$w>,)?
1587                    $(ResRead<$rr>,)?
1588                    $(ResWrite<$rw>,)?
1589                    $(EntWrite<$ew>,)?
1590                ) + Send + 'static,
1591                $($r: Query,)?
1592                $($w: QueryMut,)?
1593                $($rr: ResQuery,)?
1594                $($rw: ResQueryMut,)?
1595                $($ew: EntQueryMut,)?
1596            {
1597                fn from(value: F) -> Self {
1598                    SystemDesc::new().with_system(value)
1599                }
1600            }
1601        };
1602    }
1603
1604    #[allow(non_camel_case_types)]
1605    type o = Ph; // easy to see where it is.
1606
1607    _impl!((o , o , o , o , o ), ((), (), (), (), ()));
1608    _impl!((R,  o , o , o , o ), (R,  (), (), (), ()), r=R);
1609    _impl!((o , W,  o , o , o ), ((), W,  (), (), ()), w=W);
1610    _impl!((R,  W,  o , o , o ), (R,  W,  (), (), ()), r=R, w=W);
1611    _impl!((o , o , RR, o , o ), ((), (), RR, (), ()), rr=RR);
1612    _impl!((R,  o , RR, o , o ), (R,  (), RR, (), ()), r=R, rr=RR);
1613    _impl!((o , W,  RR, o , o ), ((), W,  RR, (), ()), w=W, rr=RR);
1614    _impl!((R,  W,  RR, o , o ), (R,  W,  RR, (), ()), r=R, w=W, rr=RR);
1615    _impl!((o , o , o , RW, o ), ((), (), (), RW, ()), rw=RW);
1616    _impl!((R,  o , o , RW, o ), (R,  (), (), RW, ()), r=R, rw=RW);
1617    _impl!((o , W,  o , RW, o ), ((), W,  (), RW, ()), w=W, rw=RW);
1618    _impl!((R,  W,  o , RW, o ), (R,  W,  (), RW, ()), r=R, w=W, rw=RW);
1619    _impl!((o , o , RR, RW, o ), ((), (), RR, RW, ()), rr=RR, rw=RW);
1620    _impl!((R,  o , RR, RW, o ), (R,  (), RR, RW, ()), r=R, rr=RR, rw=RW);
1621    _impl!((o , W,  RR, RW, o ), ((), W,  RR, RW, ()), w=W, rr=RR, rw=RW);
1622    _impl!((R,  W,  RR, RW, o ), (R,  W,  RR, RW, ()), r=R, w=W, rr=RR, rw=RW);
1623
1624    _impl!((o , o , o , o , EW), ((), (), (), (), EW), ew=EW);
1625    _impl!((R,  o , o , o , EW), (R,  (), (), (), EW), r=R, ew=EW);
1626    _impl!((o , W,  o , o , EW), ((), W,  (), (), EW), w=W, ew=EW);
1627    _impl!((R,  W,  o , o , EW), (R,  W,  (), (), EW), r=R, w=W, ew=EW);
1628    _impl!((o , o , RR, o , EW), ((), (), RR, (), EW), rr=RR, ew=EW);
1629    _impl!((R,  o , RR, o , EW), (R,  (), RR, (), EW), r=R, rr=RR, ew=EW);
1630    _impl!((o , W,  RR, o , EW), ((), W,  RR, (), EW), w=W, rr=RR, ew=EW);
1631    _impl!((R,  W,  RR, o , EW), (R,  W,  RR, (), EW), r=R, w=W, rr=RR, ew=EW);
1632    _impl!((o , o , o , RW, EW), ((), (), (), RW, EW), rw=RW, ew=EW);
1633    _impl!((R,  o , o , RW, EW), (R,  (), (), RW, EW), r=R, rw=RW, ew=EW);
1634    _impl!((o , W,  o , RW, EW), ((), W,  (), RW, EW), w=W, rw=RW, ew=EW);
1635    _impl!((R,  W,  o , RW, EW), (R,  W,  (), RW, EW), r=R, w=W, rw=RW, ew=EW);
1636    _impl!((o , o , RR, RW, EW), ((), (), RR, RW, EW), rr=RR, rw=RW, ew=EW);
1637    _impl!((R,  o , RR, RW, EW), (R,  (), RR, RW, EW), r=R, rr=RR, rw=RW, ew=EW);
1638    _impl!((o , W,  RR, RW, EW), ((), W,  RR, RW, EW), w=W, rr=RR, rw=RW, ew=EW);
1639    _impl!((R,  W,  RR, RW, EW), (R,  W,  RR, RW, EW), r=R, w=W, rr=RR, rw=RW, ew=EW);
1640}
1641
1642/// A internal type for support flexible APIs.
1643//
1644// When it comes to use cases,
1645// imagine that we'd like to accept 'struct' or 'closure' systems
1646// in a function like this,
1647// - fn register<S: System>(s: s) {}
1648//
1649// However, to implement `System` for every possible 'closure',
1650// it must stop by `FnSystem` for blanket impl.
1651// That's why we need a type to bond 'struct' and 'closure' together.
1652// Conversions of 'struct' and 'closure' are as follows.
1653// - FnMut -> FnSystem: System (for blanket impl) -> SystemBond
1654// - Struct: System -------------------------------> SystemBond
1655//
1656// So, we can modify our function like this,
1657// - fn register<S: Into<SystemBond>>(s: S) {}
1658#[derive(Debug)]
1659#[repr(transparent)]
1660pub struct SystemBond<S>(S);
1661
1662impl<S> SystemBond<S> {
1663    pub(crate) fn into_inner(self) -> S {
1664        self.0
1665    }
1666}
1667
1668impl<S: System> From<S> for SystemBond<S> {
1669    fn from(value: S) -> Self {
1670        Self(value)
1671    }
1672}
1673
1674/// Monotonically increasing count over scheduling.
1675///
1676/// When scheduling occurs, this counter increases by 1.
1677pub type Tick = u64;
1678
1679#[cfg(test)]
1680mod tests {
1681    use super::*;
1682
1683    #[test]
1684    fn test_systemgroup_unregister_volatile() {
1685        let mut sgroup = SystemGroup::<hash::RandomState>::new(0);
1686
1687        // Registers an inactive & volatile system.
1688        // Active: 0, Inactive: 1, Volatile: 1
1689        let mut sdata: SystemData = ().into_data();
1690        let sid = sgroup.next_system_id();
1691        sdata.id = sid;
1692        sgroup.register(sdata, true).unwrap();
1693        validate_len(&sgroup, 0, 1, 1);
1694
1695        // Unregisters the system.
1696        // Active: 0, Inactive: 0, Volatile: 0
1697        sgroup.unregister(&sid).unwrap();
1698        sgroup.drain_dead();
1699        validate_len(&sgroup, 0, 0, 0);
1700    }
1701
1702    #[test]
1703    fn test_systemgroup_mixed_operations() {
1704        let mut sgroup = SystemGroup::<hash::RandomState>::new(0);
1705
1706        // Registers an inactive & non-volatile system.
1707        // Active: 0, Inactive: 1, Volatile: 0
1708        let mut sdata: SystemData = ().into_data();
1709        let sid_a = sgroup.next_system_id();
1710        sdata.id = sid_a;
1711        sgroup.register(sdata, false).unwrap();
1712        validate_len(&sgroup, 0, 1, 0);
1713
1714        // Activates the system.
1715        // Active: 1, Inactive: 0, Volatile: 0
1716        sgroup.activate(&sid_a, InsertPos::Back, 1).unwrap();
1717        validate_len(&sgroup, 1, 0, 0);
1718
1719        // Registers an inactive & volatile system.
1720        // Active: 1, Inactive: 1, Volatile: 1
1721        let mut sdata: SystemData = ().into_data();
1722        let sid_b = sgroup.next_system_id();
1723        sdata.id = sid_b;
1724        sgroup.register(sdata, true).unwrap();
1725        validate_len(&sgroup, 1, 1, 1);
1726
1727        // Activates the system.
1728        // Active: 2, Inactive: 0, Volatile: 1
1729        sgroup.activate(&sid_b, InsertPos::Back, 2).unwrap();
1730        validate_len(&sgroup, 2, 0, 1);
1731
1732        // Calls tick. Non-volatile system will be inactivated.
1733        // Active: 1, Inactive: 1, Volatile: 1
1734        sgroup.tick();
1735        sgroup.drain_dead();
1736        validate_len(&sgroup, 1, 1, 1);
1737
1738        // Calls tick. Volatile system will be discarded.
1739        // Active: 0, Inactive: 1, Volatile: 0
1740        sgroup.tick();
1741        sgroup.drain_dead();
1742        validate_len(&sgroup, 0, 1, 0);
1743
1744        // Unregisters the remained system.
1745        // Active: 0, Inactive: 0, Volatile: 0
1746        sgroup.unregister(&sid_a).unwrap();
1747        sgroup.drain_dead();
1748        validate_len(&sgroup, 0, 0, 0);
1749    }
1750
1751    fn validate_len<S>(sgroup: &SystemGroup<S>, act: usize, inact: usize, vol: usize)
1752    where
1753        S: BuildHasher + Default,
1754    {
1755        assert_eq!(sgroup.active.len(), act);
1756        assert_eq!(sgroup.inactive.len(), inact);
1757        assert_eq!(sgroup.volatile.len(), vol);
1758    }
1759}