my_ecs/ecs/
entry.rs

1use super::{
2    cache::{CacheStorage, RefreshCacheStorage},
3    cmd::Command,
4    ent::{
5        component::Components,
6        entity::{ContainEntity, Entity, EntityId, EntityIndex, EntityKeyRef},
7        storage::{AsEntityReg, EntityContainer, EntityReg, EntityStorage},
8    },
9    post::{Commander, Post},
10    resource::{Resource, ResourceDesc, ResourceIndex, ResourceKey, ResourceStorage},
11    sched::{
12        comm::{command_channel, CommandReceiver, CommandSender},
13        ctrl::Scheduler,
14    },
15    sys::{
16        storage::SystemStorage,
17        system::{
18            FnOnceSystem, InsertPos, PoisonedSystem, System, SystemData, SystemDesc, SystemFlags,
19            SystemId, Tick,
20        },
21    },
22    worker::Work,
23    DynResult, EcsError,
24};
25use crate::util::{macros::debug_format, Or, With, WithResult};
26use my_ecs_macros::repeat_macro;
27use std::{
28    any::Any,
29    error::Error,
30    fmt::Debug,
31    hash::{BuildHasher, RandomState},
32    marker::PhantomData,
33    mem,
34    ops::{Deref, DerefMut},
35    ptr::NonNull,
36    rc::Rc,
37    sync::Arc,
38    thread,
39};
40
41pub mod prelude {
42    pub use super::{Ecs, EcsApp, EcsEntry, EcsExt, HelpExecuteManyCommands, LeakedEcsApp};
43}
44
45/// Common interafaces that ECS instance should provide to clients.
46///
47/// ECS instance should provide some methods for adding/removing entities,
48/// resources, and systems. Of cource compoenets are included in entities.
49/// Moreover, ECS insance is required to be able to execute commands without
50/// wrapping them in systems.
51pub trait EcsEntry {
52    // === System methods ===
53
54    /// Adds the given systems.
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use my_ecs::prelude::*;
60    ///
61    /// fn system0() { /* ... */ }
62    /// fn system1() { /* ... */ }
63    ///
64    /// Ecs::default(WorkerPool::new(), [])
65    ///     .add_systems((system0, system1))
66    ///     .unwrap();
67    /// ```
68    fn add_systems<T, Systems>(&mut self, descs: T) -> WithResult<&mut Self, (), EcsError>
69    where
70        T: HelpAddManySystems<Systems>,
71    {
72        descs.add_systems(self)
73    }
74
75    /// Adds the given system.
76    ///
77    /// # Examples
78    ///
79    /// ```
80    /// use my_ecs::prelude::*;
81    ///
82    /// fn system() { /* ... */ }
83    ///
84    /// Ecs::default(WorkerPool::new(), [])
85    ///     .add_system(system)
86    ///     .unwrap();
87    /// ```
88    fn add_system<T, Sys>(
89        &mut self,
90        desc: T,
91    ) -> WithResult<&mut Self, SystemId, EcsError<SystemDesc<Sys>>>
92    where
93        T: Into<SystemDesc<Sys>>,
94        Sys: System;
95
96    /// Adds the given [`FnOnce`] systems.
97    ///
98    /// # Examples
99    ///
100    /// ```
101    /// use my_ecs::prelude::*;
102    ///
103    /// let s = "string0".to_owned();
104    /// let system0 = move || { drop(s); };
105    /// let s = "string1".to_owned();
106    /// let system1 = move || { drop(s); };
107    ///
108    /// Ecs::default(WorkerPool::new(), [])
109    ///     .add_once_systems((system0, system1))
110    ///     .unwrap();
111    /// ```
112    fn add_once_systems<T, Once>(&mut self, descs: T) -> WithResult<&mut Self, (), EcsError>
113    where
114        T: HelpAddManyOnce<Once>,
115    {
116        descs.add_once_systems(self)
117    }
118
119    /// Adds the given [`FnOnce`] system.
120    ///
121    /// # Examples
122    ///
123    /// ```
124    /// use my_ecs::prelude::*;
125    ///
126    /// let s = "string0".to_owned();
127    /// let system = move || { drop(s); };
128    ///
129    /// Ecs::default(WorkerPool::new(), [])
130    ///     .add_once_system(system)
131    ///     .unwrap();
132    /// ```
133    fn add_once_system<T, Req, F>(
134        &mut self,
135        sys: T,
136    ) -> WithResult<&mut Self, SystemId, EcsError<SystemDesc<FnOnceSystem<Req, F>>>>
137    where
138        T: Into<FnOnceSystem<Req, F>>,
139        FnOnceSystem<Req, F>: System;
140
141    /// Unregisters an inactive system for the given system id.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// use my_ecs::prelude::*;
147    ///
148    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
149    ///
150    /// // Adds an inactive empty system.
151    /// let desc = SystemDesc::new().with_activation(0, InsertPos::Back);
152    /// let sid = ecs.add_system(desc).unwrap();
153    ///
154    /// let res = ecs.unregister_system(sid);
155    /// assert!(res.is_ok());
156    /// ```
157    fn unregister_system(&mut self, sid: SystemId) -> WithResult<&mut Self, (), EcsError>;
158
159    /// Activates a system for the given system id if it's not active.
160    ///
161    /// If the system is already active, returns error.
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// use my_ecs::prelude::*;
167    ///
168    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
169    ///
170    /// // Active system cannot be activated again.
171    /// let sid = ecs.add_system(|| { /* ... */ }).unwrap();
172    /// let res = ecs.activate_system(sid, InsertPos::Back, 2);
173    /// assert!(res.is_err());
174    ///
175    /// // Adds an inactive empty system.
176    /// let desc = SystemDesc::new().with_activation(0, InsertPos::Back);
177    /// let sid = ecs.add_system(desc).unwrap();
178    /// let res = ecs.activate_system(sid, InsertPos::Back, 2);
179    /// assert!(res.is_ok());
180    /// ```
181    fn activate_system(
182        &mut self,
183        target: SystemId,
184        at: InsertPos,
185        live: Tick,
186    ) -> WithResult<&mut Self, (), EcsError>;
187
188    /// Inactivates a system for the given system id.
189    ///
190    /// If the system is already inactive, nothing takes place and returns Ok.
191    ///
192    /// # Examples
193    ///
194    /// ```
195    /// use my_ecs::prelude::*;
196    ///
197    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
198    ///
199    /// // Inactivates an inactive system takes no effect.
200    /// let desc = SystemDesc::new().with_activation(0, InsertPos::Back);
201    /// let sid = ecs.add_system(desc).unwrap();
202    /// let res = ecs.inactivate_system(sid);
203    /// assert!(res.is_ok());
204    ///
205    /// // Inactivates an active system.
206    /// let sid = ecs.add_system(|| { /* ... */ }).unwrap();
207    /// let res = ecs.inactivate_system(sid);
208    /// assert!(res.is_ok());
209    /// ```
210    fn inactivate_system(&mut self, sid: SystemId) -> WithResult<&mut Self, (), EcsError>;
211
212    // === Entity methods ===
213
214    /// Registers an entity type.
215    ///
216    /// # Examples
217    ///
218    /// ```
219    /// use my_ecs::prelude::*;
220    ///
221    /// #[derive(Entity)] struct E { c: C }
222    /// #[derive(Component)] struct C;
223    ///
224    /// Ecs::default(WorkerPool::new(), [])
225    ///     .register_entity_of::<E>()
226    ///     .unwrap();
227    /// ```
228    fn register_entity_of<T>(&mut self) -> WithResult<&mut Self, EntityIndex, EcsError>
229    where
230        T: AsEntityReg,
231    {
232        self.register_entity(T::entity_descriptor())
233    }
234
235    /// Registers an entity type from the given descriptor.
236    ///
237    /// # Examples
238    ///
239    /// ```
240    /// use my_ecs::prelude::*;
241    ///
242    /// #[derive(Component)] struct C;
243    ///
244    /// let mut desc = EntityReg::new(
245    ///     Some(EntityName::new("my-entity".into())),
246    ///     Box::new(SparseSet::<std::hash::RandomState>::new()),
247    /// );
248    /// desc.add_component_of::<C>();
249    ///
250    /// Ecs::default(WorkerPool::new(), [])
251    ///     .register_entity(desc)
252    ///     .unwrap();
253    /// ```
254    fn register_entity(&mut self, desc: EntityReg) -> WithResult<&mut Self, EntityIndex, EcsError>;
255
256    /// Unregisters an entity type.
257    ///
258    /// # Examples
259    ///
260    /// ```
261    /// use my_ecs::prelude::*;
262    ///
263    /// #[derive(Entity)] struct E { a: Ca, b: Cb }
264    /// #[derive(Component)] struct Ca;
265    /// #[derive(Component)] struct Cb;
266    ///
267    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
268    ///
269    /// // You can unregister an entity type using entity type itself.
270    /// let res = ecs
271    ///     .register_entity_of::<E>()
272    ///     .unregister_entity::<E>()
273    ///     .take();
274    /// assert!(res.is_ok());
275    ///
276    /// // Entity can be also identified by a combination of component types.
277    /// let res = ecs
278    ///     .register_entity_of::<E>()
279    ///     .unregister_entity::<(Ca, Cb)>()
280    ///     .take();
281    /// assert!(res.is_ok());
282    /// ```
283    fn unregister_entity<C>(&mut self) -> WithResult<&mut Self, Box<dyn ContainEntity>, EcsError>
284    where
285        C: Components;
286
287    /// Adds an entity.
288    ///
289    /// # Examples
290    ///
291    /// ```
292    /// use my_ecs::prelude::*;
293    ///
294    /// #[derive(Entity)] struct E { c: C }
295    /// #[derive(Component)] struct C;
296    ///
297    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
298    /// let ei = ecs.register_entity_of::<E>().unwrap();
299    /// ecs.add_entity(ei, E { c: C }).unwrap();
300    /// ```
301    fn add_entity<E>(
302        &mut self,
303        ei: EntityIndex,
304        value: E,
305    ) -> WithResult<&mut Self, EntityId, EcsError<E>>
306    where
307        E: Entity;
308
309    /// Removes an entity.
310    ///
311    /// # Example
312    ///
313    /// ```
314    /// use my_ecs::prelude::*;
315    ///
316    /// #[derive(Entity)] struct E { c: C }
317    /// #[derive(Component)] struct C;
318    ///
319    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
320    /// let ei = ecs.register_entity_of::<E>().unwrap();
321    /// let eid = ecs.add_entity(ei, E { c: C }).unwrap();
322    /// let res = ecs.remove_entity(eid);
323    /// assert!(res.is_ok());
324    /// ```
325    fn remove_entity(&mut self, eid: EntityId) -> WithResult<&mut Self, (), EcsError>;
326
327    // === Resource methods ===
328
329    /// Adds the given resources.
330    ///
331    /// # Examples
332    ///
333    /// ```
334    /// use my_ecs::prelude::*;
335    ///
336    /// #[derive(Resource)] struct Ra(i32);
337    /// #[derive(Resource)] struct Rb(i32);
338    ///
339    /// Ecs::default(WorkerPool::new(), [])
340    ///     .add_resources((Ra(0), Rb(1)))
341    ///     .unwrap();
342    /// ```
343    fn add_resources<T>(&mut self, descs: T) -> WithResult<&mut Self, (), EcsError>
344    where
345        T: HelpAddManyResources,
346    {
347        descs.add_resources(self)
348    }
349
350    /// Adds the given resource.
351    ///
352    /// If the same resource type was already added, returns error.
353    ///
354    /// # Examples
355    ///
356    /// ```
357    /// use my_ecs::prelude::*;
358    ///
359    /// #[derive(Resource)] struct Ra;
360    /// #[derive(Resource)] struct Rb(i32);
361    ///
362    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
363    ///
364    /// // Adds an owned resource.
365    /// let res = ecs.add_resource(Ra);
366    /// assert!(res.is_ok());
367    ///
368    /// // You cannot register the same resource type.
369    /// let res = ecs.add_resource(Ra);
370    /// assert!(res.is_err());
371    ///
372    /// // Adds a not owned resource.
373    /// let mut r = Rb(0);
374    /// let ptr = &mut r as *mut Rb;
375    /// let desc = unsafe { ResourceDesc::new().with_ptr(ptr) };
376    /// let res = ecs.add_resource(desc);
377    /// assert!(res.is_ok());
378    /// ```
379    fn add_resource<T>(
380        &mut self,
381        desc: T,
382    ) -> WithResult<&mut Self, ResourceIndex, EcsError<ResourceDesc>>
383    where
384        T: Into<ResourceDesc>;
385
386    /// Removes a resource from the given resource type.
387    ///
388    /// # Examples
389    ///
390    /// ```
391    /// use my_ecs::prelude::*;
392    ///
393    /// #[derive(Resource, Debug, PartialEq)]
394    /// struct R(i32);
395    ///
396    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
397    ///
398    /// let res = ecs
399    ///     .add_resource(R(42))
400    ///     .remove_resource::<R>()
401    ///     .unwrap();
402    /// assert_eq!(res, Some(R(42)));
403    /// ```
404    fn remove_resource<R>(&mut self) -> WithResult<&mut Self, Option<R>, EcsError>
405    where
406        R: Resource;
407
408    /// Retrieves shared reference to a resource for the given resource type.
409    ///
410    /// # Examples
411    ///
412    /// ```
413    /// use my_ecs::prelude::*;
414    ///
415    /// #[derive(Resource)] struct R(i32);
416    ///
417    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
418    ///
419    /// ecs.add_resource(R(42)).unwrap();
420    /// let r = ecs.get_resource::<R>().unwrap();
421    /// assert_eq!(r.0, 42);
422    /// ```
423    fn get_resource<R>(&self) -> Option<&R>
424    where
425        R: Resource;
426
427    /// Retrieves mutable reference to a resource for the given resource type.
428    ///
429    /// # Examples
430    ///
431    /// ```
432    /// use my_ecs::prelude::*;
433    ///
434    /// #[derive(Resource)] struct R(i32);
435    ///
436    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
437    ///
438    /// ecs.add_resource(R(42)).unwrap();
439    /// let r = ecs.get_resource_mut::<R>().unwrap();
440    /// r.0 = 43;
441    ///
442    /// let r = ecs.get_resource_mut::<R>().unwrap();
443    /// assert_eq!(r.0, 43);
444    ///
445    /// ```
446    fn get_resource_mut<R>(&mut self) -> Option<&mut R>
447    where
448        R: Resource;
449
450    /// Returns resource index for the given resource type.
451    ///
452    /// # Examples
453    ///
454    /// ```
455    /// use my_ecs::prelude::*;
456    ///
457    /// #[derive(Resource)] struct R;
458    ///
459    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
460    ///
461    /// let ei = ecs.add_resource(R).unwrap();
462    /// let found = ecs.get_resource_index::<R>().unwrap();
463    /// assert_eq!(found, ei);
464    /// ```
465    fn get_resource_index<R>(&self) -> Option<ResourceIndex>
466    where
467        R: Resource;
468
469    // === Command methods ===
470
471    /// Executes the given commands in order.
472    ///
473    /// # Examples
474    ///
475    /// ```
476    /// use my_ecs::prelude::*;
477    ///
478    /// let cmd0 = |ecs: Ecs| -> DynResult<()> { /* ... */ Ok(()) };
479    /// let cmd1 = |ecs: Ecs| -> DynResult<()> { /* ... */ Ok(()) };
480    ///
481    /// Ecs::default(WorkerPool::new(), [])
482    ///     .execute_commands((cmd0, cmd1))
483    ///     .unwrap();
484    /// ```
485    fn execute_commands<T>(
486        &mut self,
487        cmds: T,
488    ) -> WithResult<&mut Self, (), Box<dyn Error + Send + Sync + 'static>>
489    where
490        T: HelpExecuteManyCommands;
491
492    /// Execute the given command.
493    ///
494    /// # Example
495    ///
496    /// ```
497    /// use my_ecs::prelude::*;
498    ///
499    /// #[derive(Entity)] struct E { a: Ca }
500    /// #[derive(Component)] struct Ca;
501    /// #[derive(Component)] struct Cb;
502    ///
503    /// let mut ecs = Ecs::default(WorkerPool::new(), []);
504    /// let ei = ecs.register_entity_of::<E>().unwrap();
505    /// let eid = ecs.add_entity(ei, E { a: Ca }).unwrap();
506    ///
507    /// // Attaches `Cb` to `E` so that it's now (Ca, Cb);
508    /// ecs.execute_command(move |cmdr| cmdr.change_entity(eid).attach(Cb).finish())
509    ///     .unwrap();
510    ///
511    /// // We can unregister (Ca, Cb).
512    /// let res = ecs.unregister_entity::<(Ca, Cb)>();
513    /// assert!(res.is_ok());
514    /// ```
515    fn execute_command<F, R>(
516        &mut self,
517        f: F,
518    ) -> WithResult<&mut Self, (), Box<dyn Error + Send + Sync + 'static>>
519    where
520        F: FnOnce(Commander) -> R,
521        R: Command;
522
523    /// Returns errors generated from commands or futures.
524    ///
525    /// Commands and futures don't cause panic. Instead, errors are collected
526    /// in a vector. Clients can retrieve the vector using this method.
527    fn errors(&mut self) -> Vec<Box<dyn Error + Send + Sync + 'static>>;
528}
529
530/// A helper trait for [`EcsEntry::add_systems`].
531///
532/// This helper trait is implemented for tuple of anonymous systems.
533pub trait HelpAddManySystems<Systems> {
534    fn add_systems<Ecs>(self, ecs: &mut Ecs) -> WithResult<&mut Ecs, (), EcsError>
535    where
536        Ecs: EcsEntry + ?Sized;
537}
538
539/// Implements [`HelpAddManySystems`] for tuple of systems.
540macro_rules! impl_help_add_many_systems {
541    ($n:expr, $($i:expr),*) => {
542        paste::paste! {
543            #[allow(unused_parens, non_snake_case)]
544            impl<$([<A $i>], [<S $i>]),*> HelpAddManySystems<( $([<S $i>]),* )>
545                for ( $([<A $i>]),* )
546            where
547            $(
548                [<A $i>]: Into<SystemDesc<[<S $i>]>>,
549                [<S $i>]: System,
550            )*
551            {
552                fn add_systems<Ecs>(self, ecs: &mut Ecs) -> WithResult<&mut Ecs, (), EcsError>
553                where
554                    Ecs: EcsEntry + ?Sized,
555                {
556                    let ( $([<A $i>]),* ) = self;
557
558                    $(
559                        match ecs.add_system([<A $i>]).take() {
560                            Ok(_) => {}
561                            Err(e) => return WithResult::new(ecs, Err(e.without_data())),
562                        }
563                    )*
564
565                    WithResult::new(ecs, Ok(()))
566                }
567            }
568        }
569    };
570}
571repeat_macro!(impl_help_add_many_systems, 1..=8);
572
573/// A helper trait for [`EcsEntry::add_once_systems`].
574///
575/// This helper trait is implemented for tuple of anonymous once systems.
576pub trait HelpAddManyOnce<Once> {
577    fn add_once_systems<Ecs>(self, ecs: &mut Ecs) -> WithResult<&mut Ecs, (), EcsError>
578    where
579        Ecs: EcsEntry + ?Sized;
580}
581
582/// Implements [`HelpAddManyOnce`] for tuple of once systems.
583macro_rules! impl_help_add_many_once {
584    ($n:expr, $($i:expr),*) => {
585        paste::paste! {
586            #[allow(unused_parens, non_snake_case)]
587            impl<$([<A $i>], [<R $i>], [<S $i>]),*> HelpAddManyOnce<( $( [<R $i>], [<S $i>] ),* )>
588                for ( $([<A $i>]),* )
589            where
590            $(
591                [<A $i>]: Into<FnOnceSystem<[<R $i>], [<S $i>]>>,
592                FnOnceSystem<[<R $i>], [<S $i>]>: System,
593            )*
594            {
595                fn add_once_systems<Ecs>(self, ecs: &mut Ecs) -> WithResult<&mut Ecs, (), EcsError>
596                where
597                    Ecs: EcsEntry + ?Sized,
598                {
599                    let ( $([<A $i>]),* ) = self;
600
601                    $(
602                        match ecs.add_once_system([<A $i>]).take() {
603                            Ok(_) => {}
604                            Err(e) => return WithResult::new(ecs, Err(e.without_data())),
605                        }
606                    )*
607
608                    WithResult::new(ecs, Ok(()))
609                }
610            }
611        }
612    };
613}
614repeat_macro!(impl_help_add_many_once, 1..=8);
615
616/// A helper trait for [`EcsEntry::add_resources`].
617///
618/// This helper trait is implemented for tuple of anonymous resources.
619pub trait HelpAddManyResources {
620    fn add_resources<Ecs>(self, ecs: &mut Ecs) -> WithResult<&mut Ecs, (), EcsError>
621    where
622        Ecs: EcsEntry + ?Sized;
623}
624
625/// Implements [`HelpAddManyResources`] for tuple of resources.
626macro_rules! impl_help_add_many_resources {
627    ($n:expr, $($i:expr),*) => {
628        paste::paste! {
629            #[allow(unused_parens, non_snake_case)]
630            impl<$([<A $i>]),*> HelpAddManyResources for ( $([<A $i>]),* )
631            where
632            $(
633                [<A $i>]: Into<ResourceDesc>,
634            )*
635            {
636                fn add_resources<Ecs>(
637                    self,
638                    ecs: &mut Ecs
639                ) -> WithResult<&mut Ecs, (), EcsError>
640                where
641                    Ecs: EcsEntry + ?Sized,
642                {
643                    let ( $([<A $i>]),* ) = self;
644
645                    $(
646                        match ecs.add_resource([<A $i>]).take() {
647                            Ok(_) => {}
648                            Err(e) => return WithResult::new(ecs, Err(e.without_data())),
649                        }
650                    )*
651
652                    WithResult::new(ecs, Ok(()))
653                }
654            }
655        }
656    };
657}
658repeat_macro!(impl_help_add_many_resources, 1..=8);
659
660/// A helper trait for [`EcsEntry::execute_commands`].
661///
662/// This helper trait is implemented for tuple of anonymous commands.
663pub trait HelpExecuteManyCommands {
664    fn command(&mut self, ecs: Ecs<'_>) -> DynResult<()>;
665}
666
667/// Implements [`HelpExecuteManyCommands`] for tuple of commands.
668macro_rules! impl_help_execute_many_commands {
669    (1, 0) => {
670        impl<A0: Command> HelpExecuteManyCommands for A0 {
671            fn command(&mut self, ecs: Ecs<'_>) -> DynResult<()> {
672                self.command(ecs)
673            }
674        }
675    };
676    ($n:expr, $($i:expr),*) => {
677        paste::paste! {
678            #[allow(unused_parens)]
679            impl<$([<A $i>]: Command),*> HelpExecuteManyCommands for ( $([<A $i>]),* ) {
680                fn command(&mut self, ecs: Ecs<'_>) -> DynResult<()> {
681                    $(
682                        match self.$i.command(unsafe { ecs.copy() }) {
683                            Ok(()) => {}
684                            Err(e) => return Err(e),
685                        }
686                    )*
687                    Ok(())
688                }
689            }
690        }
691    };
692}
693repeat_macro!(impl_help_execute_many_commands, 1..=8);
694
695/// Internal function pointer table of [`EcsApp`].
696/// 
697/// # Why we need function pointer
698/// 
699/// To declare [`Command`], clients need to put `EcsApp` as a parameter in their
700/// functions. But `EcsApp` is too verbose. So it is where [`Ecs`] comes in to
701/// play. `Ecs` doesn't have complex generic parameters so clients can easily
702/// remember and use it. This vtable helps `Ecs` to call functions in `EcsApp`.
703#[rustfmt::skip]
704#[allow(clippy::type_complexity)]
705#[derive(Debug)]
706struct EcsVTable {
707    // === System methods ===
708
709    register_system_inner:
710        unsafe fn(NonNull<u8>, SystemData, u16, bool, bool)
711        -> Result<SystemId, EcsError<SystemData>>,
712
713    unregister_system_inner:
714        unsafe fn(NonNull<u8>, &SystemId) -> Result<(), EcsError>,
715
716    activate_system_inner:
717        unsafe fn(NonNull<u8>, SystemId, InsertPos, Tick)
718        -> Result<(), EcsError>,
719
720    inactivate_system_inner:
721        unsafe fn(NonNull<u8>, &SystemId) -> Result<(), EcsError>,
722
723    // === Entity methods ===
724
725    register_entity_inner:
726        unsafe fn(NonNull<u8>, EntityReg) -> Result<EntityIndex, EcsError>,
727
728    unregister_entity_inner:
729        unsafe fn(NonNull<u8>, EntityKeyRef<'_>) -> Result<Box<dyn ContainEntity>, EcsError>,
730
731    get_entity_container_mut:
732        unsafe fn(NonNull<u8>, EntityKeyRef<'_>) -> Option<&mut EntityContainer>,
733
734    // === Resource methods ===
735
736    add_resource_inner:
737        unsafe fn(NonNull<u8>, ResourceDesc)
738        -> Result<ResourceIndex, EcsError<ResourceDesc>>,
739
740    remove_resource_inner:
741        unsafe fn(NonNull<u8>, &ResourceKey)
742        -> Result<Option<Box<dyn Any>>, EcsError>,
743
744    get_resource_inner:
745        unsafe fn(NonNull<u8>, &ResourceKey) -> Option<NonNull<u8>>,
746
747    get_resource_mut_inner:
748        unsafe fn(NonNull<u8>, &ResourceKey) -> Option<NonNull<u8>>,
749
750    get_resource_index_inner:
751        unsafe fn(NonNull<u8>, &ResourceKey) -> Option<ResourceIndex>,
752
753    // === Etc. ===
754
755    post_ptr:
756        unsafe fn(NonNull<u8>) -> NonNull<Post>,
757
758    step:
759        unsafe fn(NonNull<u8>),
760    
761    errors:
762        unsafe fn(NonNull<u8>) -> Vec<Box<dyn Error + Send + Sync + 'static>>,
763}
764
765impl EcsVTable {
766    fn new<W, S>() -> Self
767    where
768        W: Work + 'static,
769        S: BuildHasher + Default + 'static,
770    {
771        unsafe fn register_system_inner<W, S>(
772            this: NonNull<u8>,
773            sdata: SystemData,
774            group_index: u16,
775            volatile: bool,
776            private: bool,
777        ) -> Result<SystemId, EcsError<SystemData>>
778        where
779            W: Work + 'static,
780            S: BuildHasher + Default + 'static,
781        {
782            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
783            this.register_system_inner(sdata, group_index, volatile, private)
784        }
785
786        unsafe fn unregister_system_inner<W, S>(
787            this: NonNull<u8>,
788            sid: &SystemId,
789        ) -> Result<(), EcsError>
790        where
791            W: Work + 'static,
792            S: BuildHasher + Default + 'static,
793        {
794            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
795            this.unregister_system_inner(sid)
796        }
797
798        unsafe fn activate_system_inner<W, S>(
799            this: NonNull<u8>,
800            target: SystemId,
801            at: InsertPos,
802            live: Tick,
803        ) -> Result<(), EcsError>
804        where
805            W: Work + 'static,
806            S: BuildHasher + Default + 'static,
807        {
808            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
809            this.activate_system_inner(target, at, live)
810        }
811
812        unsafe fn inactivate_system_inner<W, S>(
813            this: NonNull<u8>,
814            sid: &SystemId,
815        ) -> Result<(), EcsError>
816        where
817            W: Work + 'static,
818            S: BuildHasher + Default + 'static,
819        {
820            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
821            this.inactivate_system_inner(sid)
822        }
823
824        unsafe fn register_entity_inner<W, S>(
825            this: NonNull<u8>,
826            desc: EntityReg,
827        ) -> Result<EntityIndex, EcsError>
828        where
829            W: Work + 'static,
830            S: BuildHasher + Default + 'static,
831        {
832            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
833            this.register_entity_inner(desc)
834        }
835
836        unsafe fn unregister_entity_inner<W, S>(
837            this: NonNull<u8>,
838            ekey: EntityKeyRef<'_>,
839        ) -> Result<Box<dyn ContainEntity>, EcsError>
840        where
841            W: Work + 'static,
842            S: BuildHasher + Default + 'static,
843        {
844            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
845            this.unregister_entity_inner(ekey)
846        }
847
848        unsafe fn get_entity_container_mut<'o, W, S>(
849            this: NonNull<u8>,
850            ekey: EntityKeyRef<'_>,
851        ) -> Option<&'o mut EntityContainer>
852        where
853            W: Work + 'static,
854            S: BuildHasher + Default + 'static,
855        {
856            let this: &'o mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
857            this.get_entity_container_mut(ekey)
858        }
859
860        unsafe fn add_resource_inner<W, S>(
861            this: NonNull<u8>,
862            desc: ResourceDesc,
863        ) -> Result<ResourceIndex, EcsError<ResourceDesc>>
864        where
865            W: Work + 'static,
866            S: BuildHasher + Default + 'static,
867        {
868            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
869            this.add_resource_inner(desc)
870        }
871
872        unsafe fn remove_resource_inner<W, S>(
873            this: NonNull<u8>,
874            rkey: &ResourceKey,
875        ) -> Result<Option<Box<dyn Any>>, EcsError>
876        where
877            W: Work + 'static,
878            S: BuildHasher + Default + 'static,
879        {
880            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
881            this.remove_resource_inner(rkey)
882        }
883
884        unsafe fn get_resource_inner<W, S>(
885            this: NonNull<u8>,
886            rkey: &ResourceKey,
887        ) -> Option<NonNull<u8>>
888        where
889            W: Work + 'static,
890            S: BuildHasher + Default + 'static,
891        {
892            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
893            this.get_resource_inner(rkey)
894        }
895
896        unsafe fn get_resource_mut_inner<W, S>(
897            this: NonNull<u8>,
898            rkey: &ResourceKey,
899        ) -> Option<NonNull<u8>>
900        where
901            W: Work + 'static,
902            S: BuildHasher + Default + 'static,
903        {
904            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
905            this.get_resource_mut_inner(rkey)
906        }
907
908        unsafe fn get_resource_index_inner<W, S>(
909            this: NonNull<u8>,
910            rkey: &ResourceKey,
911        ) -> Option<ResourceIndex>
912        where
913            W: Work + 'static,
914            S: BuildHasher + Default + 'static,
915        {
916            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
917            this.get_resource_index_inner(rkey)
918        }
919
920        unsafe fn post_ptr<W, S>(this: NonNull<u8>) -> NonNull<Post>
921        where
922            W: Work + 'static,
923            S: BuildHasher + Default + 'static,
924        {
925            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
926            let post = this.get_resource::<Post>().unwrap();
927            unsafe { NonNull::new_unchecked((post as *const Post).cast_mut()) }
928        }
929
930        unsafe fn step<W, S>(this: NonNull<u8>)
931        where
932            W: Work + 'static,
933            S: BuildHasher + Default + 'static,
934        {
935            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
936            this.step();
937        }
938
939        unsafe fn errors<W, S>(this: NonNull<u8>) -> Vec<Box<dyn Error + Send + Sync + 'static>>
940        where
941            W: Work + 'static,
942            S: BuildHasher + Default + 'static,
943        {
944            let this: &mut EcsApp<W, S> = unsafe { this.cast().as_mut() };
945            this.errors()
946        }
947
948        Self {
949            register_system_inner: register_system_inner::<W, S>,
950            unregister_system_inner: unregister_system_inner::<W, S>,
951            activate_system_inner: activate_system_inner::<W, S>,
952            inactivate_system_inner: inactivate_system_inner::<W, S>,
953            register_entity_inner: register_entity_inner::<W, S>,
954            unregister_entity_inner: unregister_entity_inner::<W, S>,
955            get_entity_container_mut: get_entity_container_mut::<W, S>,
956            add_resource_inner: add_resource_inner::<W, S>,
957            remove_resource_inner: remove_resource_inner::<W, S>,
958            get_resource_inner: get_resource_inner::<W, S>,
959            get_resource_mut_inner: get_resource_mut_inner::<W, S>,
960            get_resource_index_inner: get_resource_index_inner::<W, S>,
961            post_ptr: post_ptr::<W, S>,
962            step: step::<W, S>,
963            errors: errors::<W, S>,
964        }
965    }
966}
967
968/// A handle to [`EcsApp`], which is real ecs instance.
969///
970/// This type is just for easy use in some cases such as writing a command. By
971/// removing verbose generic parameters, clients can declare parameters as `Ecs`
972/// instead of `EcsApp<W, S>` in their command functions for example.
973//
974// Do not implement Clone. This must be carefully cloned.
975#[derive(Debug)]
976pub struct Ecs<'ecs> {
977    /// Type erased pointer to [`EcsApp`].
978    this: NonNull<u8>,
979
980    /// Function table of the [`EcsApp`].
981    vtable: NonNull<EcsVTable>,
982
983    /// Borrows [`EcsApp`] mutably.
984    _marker: PhantomData<&'ecs mut ()>,
985}
986
987impl<'ecs> Ecs<'ecs> {
988    /// Creates [`EcsApp`] with the given worker pool and group information.
989    ///
990    /// The returned instance uses [`RandomState`] as hasher builder for its
991    /// internal data structures. If you want another, call [`Ecs::create`]
992    /// instead.
993    ///
994    /// # Examples
995    ///
996    /// ```
997    /// use my_ecs::prelude::*;
998    ///
999    /// // Creates `EcsApp` with one group consisting of 4 workers.
1000    /// let pool = WorkerPool::with_len(4);
1001    /// let ecs = Ecs::default(pool, [4]);
1002    ///
1003    /// // Creates `EcsApp` with two groups consisting of 2 workers respectively.
1004    /// let pool = WorkerPool::with_len(4);
1005    /// let ecs = Ecs::default(pool, [2, 2]);
1006    /// ```
1007    pub fn default<Wp, W, G>(pool: Wp, groups: G) -> EcsApp<W, RandomState>
1008    where
1009        Wp: Into<Vec<W>>,
1010        W: Work + 'static,
1011        G: AsRef<[usize]>,
1012    {
1013        Self::create(pool.into(), groups.as_ref())
1014    }
1015
1016    /// Creates [`EcsApp`] with the given workers, group information, and hasher
1017    /// builder type.
1018    ///
1019    /// # Examples
1020    ///
1021    /// ```
1022    /// use my_ecs::prelude::*;
1023    /// use std::hash::{BuildHasher, DefaultHasher};
1024    ///
1025    /// // Something like `std::hash::RandomState`.
1026    /// #[derive(Default)] struct FixedState;
1027    /// impl BuildHasher for FixedState {
1028    ///     type Hasher = DefaultHasher;
1029    ///     fn build_hasher(&self) -> Self::Hasher {
1030    ///         DefaultHasher::new()
1031    ///     }
1032    /// }
1033    ///
1034    /// // Creates `EcsApp` with one group consisting of 4 workers.
1035    /// let pool = WorkerPool::with_len(4);
1036    /// let ecs: EcsApp<_, FixedState> = Ecs::create(pool, [4]);
1037    ///
1038    /// // Creates `EcsApp` with two groups consisting of 2 workers respectively.
1039    /// let pool = WorkerPool::with_len(4);
1040    /// let ecs: EcsApp<_, FixedState> = Ecs::create(pool, [2, 2]);
1041    /// ```
1042    pub fn create<Wp, W, G, S>(pool: Wp, groups: G) -> EcsApp<W, S>
1043    where
1044        Wp: Into<Vec<W>>,
1045        W: Work + 'static,
1046        G: AsRef<[usize]>,
1047        S: BuildHasher + Default + 'static,
1048    {
1049        EcsApp::new(pool.into(), groups.as_ref())
1050    }
1051
1052    fn new<W, S>(ecs: &'ecs mut EcsApp<W, S>) -> Self
1053    where
1054        W: Work + 'static,
1055        S: BuildHasher + Default + 'static,
1056    {
1057        unsafe {
1058            let this = NonNull::new_unchecked(ecs as *mut _ as *mut u8);
1059            let vtable = NonNull::new_unchecked(&mut ecs.vtable as *mut _);
1060            Self {
1061                this,
1062                vtable,
1063                _marker: PhantomData,
1064            }
1065        }
1066    }
1067
1068    /// # Safety
1069    ///
1070    /// Caller must guarantee that the returned replica will not violate pointer
1071    /// rules. In other words, callers must comply pointer aliasing and must not
1072    /// use it after free.
1073    pub(crate) unsafe fn copy(&self) -> Self {
1074        Self {
1075            this: self.this,
1076            vtable: self.vtable,
1077            _marker: self._marker,
1078        }
1079    }
1080
1081    /// Returns pointer to a certain entity container for the given entity key.
1082    ///
1083    /// Note that you can acquire two or more entity container pointers at a
1084    /// time. But you must check pointer uniqueness when you're turning them
1085    /// into mutable references.
1086    pub(crate) fn entity_container_ptr(
1087        &self,
1088        ekey: EntityKeyRef<'_>,
1089    ) -> Option<NonNull<EntityContainer>> {
1090        unsafe {
1091            let vtable = self.vtable.as_ref();
1092            (vtable.get_entity_container_mut)(self.this, ekey)
1093                .map(|cont| NonNull::new_unchecked(cont as *mut _))
1094        }
1095    }
1096
1097    pub(crate) fn post_ptr(&self) -> NonNull<Post> {
1098        unsafe {
1099            let vtable = self.vtable.as_ref();
1100            (vtable.post_ptr)(self.this)
1101        }
1102    }
1103}
1104
1105impl EcsEntry for Ecs<'_> {
1106    fn add_system<T, Sys>(
1107        &mut self,
1108        desc: T,
1109    ) -> WithResult<&mut Self, SystemId, EcsError<SystemDesc<Sys>>>
1110    where
1111        T: Into<SystemDesc<Sys>>,
1112        Sys: System,
1113    {
1114        let desc = desc.into();
1115        let SystemDesc {
1116            sys,
1117            private,
1118            group_index,
1119            volatile,
1120            activation: (live, insert_at),
1121        } = desc;
1122        let sdata = match sys {
1123            Or::A(sys) => sys.into_data(),
1124            Or::B(sdata) => sdata,
1125        };
1126
1127        // Registers the system.
1128        let res = unsafe {
1129            let vtable = self.vtable.as_ref();
1130            (vtable.register_system_inner)(self.this, sdata, group_index, volatile, private)
1131        };
1132
1133        // TODO: If we failed to activate it, we have to unregister it.
1134        //
1135        // Activates the system.
1136        if let Ok(sid) = res.as_ref() {
1137            if live > 0 {
1138                let must_ok = self.activate_system(*sid, insert_at, live);
1139                assert!(must_ok.is_ok());
1140            }
1141        }
1142
1143        let res = res.map_err(|err| {
1144            err.map_data(|sdata| {
1145                let sys = match sdata.try_into_any() {
1146                    Ok(any) => {
1147                        let sys = *any.downcast::<Sys>().unwrap();
1148                        Or::A(sys)
1149                    }
1150                    Err(sdata) => Or::B(sdata),
1151                };
1152                SystemDesc {
1153                    sys,
1154                    private,
1155                    group_index,
1156                    volatile,
1157                    activation: (live, insert_at),
1158                }
1159            })
1160        });
1161        WithResult::new(self, res)
1162    }
1163
1164    fn add_once_system<T, Req, F>(
1165        &mut self,
1166        sys: T,
1167    ) -> WithResult<&mut Self, SystemId, EcsError<SystemDesc<FnOnceSystem<Req, F>>>>
1168    where
1169        T: Into<FnOnceSystem<Req, F>>,
1170        FnOnceSystem<Req, F>: System,
1171    {
1172        let desc = SystemDesc::new().with_once(sys);
1173        self.add_system(desc)
1174    }
1175
1176    fn unregister_system(&mut self, sid: SystemId) -> WithResult<&mut Self, (), EcsError> {
1177        let res = unsafe {
1178            let vtable = self.vtable.as_ref();
1179            (vtable.unregister_system_inner)(self.this, &sid)
1180        };
1181        WithResult::new(self, res)
1182    }
1183
1184    fn activate_system(
1185        &mut self,
1186        target: SystemId,
1187        at: InsertPos,
1188        live: Tick,
1189    ) -> WithResult<&mut Self, (), EcsError> {
1190        let res = unsafe {
1191            let vtable = self.vtable.as_ref();
1192            (vtable.activate_system_inner)(self.this, target, at, live)
1193        };
1194        WithResult::new(self, res)
1195    }
1196
1197    fn inactivate_system(&mut self, sid: SystemId) -> WithResult<&mut Self, (), EcsError> {
1198        let res = unsafe {
1199            let vtable = self.vtable.as_ref();
1200            (vtable.inactivate_system_inner)(self.this, &sid)
1201        };
1202        WithResult::new(self, res)
1203    }
1204
1205    fn register_entity(&mut self, desc: EntityReg) -> WithResult<&mut Self, EntityIndex, EcsError> {
1206        let res = unsafe {
1207            let vtable = self.vtable.as_ref();
1208            (vtable.register_entity_inner)(self.this, desc)
1209        };
1210        WithResult::new(self, res)
1211    }
1212
1213    fn unregister_entity<C>(&mut self) -> WithResult<&mut Self, Box<dyn ContainEntity>, EcsError>
1214    where
1215        C: Components,
1216    {
1217        let ckeys = C::sorted_keys();
1218        let ekey = EntityKeyRef::Ckeys(ckeys.as_ref());
1219        let res = unsafe {
1220            let vtable = self.vtable.as_ref();
1221            (vtable.unregister_entity_inner)(self.this, ekey)
1222        };
1223        WithResult::new(self, res)
1224    }
1225
1226    fn add_entity<E>(
1227        &mut self,
1228        ei: EntityIndex,
1229        value: E,
1230    ) -> WithResult<&mut Self, EntityId, EcsError<E>>
1231    where
1232        E: Entity,
1233    {
1234        let ekey = EntityKeyRef::Index(&ei);
1235
1236        let cont = unsafe {
1237            let vtable = self.vtable.as_ref();
1238            (vtable.get_entity_container_mut)(self.this, ekey)
1239        };
1240
1241        let res = if let Some(cont) = cont {
1242            let ri = value.move_to(&mut **cont);
1243            Ok(EntityId::new(ei, ri))
1244        } else {
1245            let reason = debug_format!("failed to find `{}`", std::any::type_name::<E>());
1246            Err(EcsError::UnknownEntity(reason, value))
1247        };
1248        WithResult::new(self, res)
1249    }
1250
1251    fn remove_entity(&mut self, eid: EntityId) -> WithResult<&mut Self, (), EcsError> {
1252        let ei = eid.container_index();
1253        let ekey = EntityKeyRef::Index(&ei);
1254
1255        let cont = unsafe {
1256            let vtable = self.vtable.as_ref();
1257            (vtable.get_entity_container_mut)(self.this, ekey)
1258        };
1259
1260        let res = if let Some(cont) = cont {
1261            let ri = eid.row_index();
1262            let is_removed = cont.remove_row(ri);
1263            if is_removed {
1264                Ok(())
1265            } else {
1266                let reason = debug_format!("failed to find an entity for {eid:?}");
1267                Err(EcsError::UnknownEntity(reason, ()))
1268            }
1269        } else {
1270            let reason = debug_format!("failed to find an entity for {eid:?}");
1271            Err(EcsError::UnknownEntity(reason, ()))
1272        };
1273        WithResult::new(self, res)
1274    }
1275
1276    fn add_resource<T>(
1277        &mut self,
1278        desc: T,
1279    ) -> WithResult<&mut Self, ResourceIndex, EcsError<ResourceDesc>>
1280    where
1281        T: Into<ResourceDesc>,
1282    {
1283        let res = unsafe {
1284            let vtable = self.vtable.as_ref();
1285            (vtable.add_resource_inner)(self.this, desc.into())
1286        };
1287        WithResult::new(self, res)
1288    }
1289
1290    fn remove_resource<R>(&mut self) -> WithResult<&mut Self, Option<R>, EcsError>
1291    where
1292        R: Resource,
1293    {
1294        let res = unsafe {
1295            let vtable = self.vtable.as_ref();
1296            (vtable.remove_resource_inner)(self.this, &R::key())
1297        };
1298        let res = res.map(|opt| opt.map(|any| *any.downcast::<R>().unwrap()));
1299        WithResult::new(self, res)
1300    }
1301
1302    fn get_resource<R>(&self) -> Option<&R>
1303    where
1304        R: Resource,
1305    {
1306        unsafe {
1307            let vtable = self.vtable.as_ref();
1308            (vtable.get_resource_inner)(self.this, &R::key()).map(|ptr| ptr.cast::<R>().as_ref())
1309        }
1310    }
1311
1312    fn get_resource_mut<R>(&mut self) -> Option<&mut R>
1313    where
1314        R: Resource,
1315    {
1316        unsafe {
1317            let vtable = self.vtable.as_ref();
1318            (vtable.get_resource_mut_inner)(self.this, &R::key())
1319                .map(|ptr| ptr.cast::<R>().as_mut())
1320        }
1321    }
1322
1323    fn get_resource_index<R>(&self) -> Option<ResourceIndex>
1324    where
1325        R: Resource,
1326    {
1327        unsafe {
1328            let vtable = self.vtable.as_ref();
1329            (vtable.get_resource_index_inner)(self.this, &R::key())
1330        }
1331    }
1332
1333    fn execute_commands<T>(
1334        &mut self,
1335        mut cmds: T,
1336    ) -> WithResult<&mut Self, (), Box<dyn Error + Send + Sync + 'static>>
1337    where
1338        T: HelpExecuteManyCommands,
1339    {
1340        let res = cmds.command(unsafe { self.copy() });
1341        WithResult::new(self, res)
1342    }
1343
1344    fn execute_command<F, R>(
1345        &mut self,
1346        f: F,
1347    ) -> WithResult<&mut Self, (), Box<dyn Error + Send + Sync + 'static>>
1348    where
1349        F: FnOnce(Commander) -> R,
1350        R: Command,
1351    {
1352        let post = self.get_resource::<Post>().unwrap();
1353        let cmdr = post.as_commander();
1354        let mut cmd = f(cmdr);
1355        let res = cmd.command(unsafe { self.copy() });
1356        WithResult::new(self, res)
1357    }
1358
1359    fn errors(&mut self) -> Vec<Box<dyn Error + Send + Sync + 'static>> {
1360        unsafe {
1361            let vtable = self.vtable.as_ref();
1362            (vtable.errors)(self.this)
1363        }
1364    }
1365}
1366
1367/// An ECS instance.
1368///
1369/// Clients can create the instance via [`Ecs::default`], [`Ecs::create`] or
1370/// [`EcsApp::new`]. It's possible to have multiple ECS instances as well if you
1371/// really need to do so, but it's recommended to have multiple groups instead
1372/// of multiple instances to reduce memory footprint and share data with ease.
1373///
1374/// * `W` - Worker type.
1375/// * `S` - Hasher builder type.
1376#[derive(Debug)]
1377pub struct EcsApp<W, S = RandomState>
1378where
1379    W: Work + 'static,
1380    S: BuildHasher + Default + 'static,
1381{
1382    /// System storage.
1383    sys_stor: SystemStorage<S>,
1384
1385    /// Entity and component storage.
1386    /// The storage contains all kinds of entities and components.
1387    ent_stor: EntityStorage<S>,
1388
1389    /// Resource storage.
1390    /// The storage contains pointers to resources.
1391    res_stor: ResourceStorage<S>,
1392
1393    cache_stor: CacheStorage<S>,
1394
1395    sched: Scheduler<W, S>,
1396
1397    cmd_errs: Vec<Box<dyn Error + Send + Sync + 'static>>,
1398
1399    vtable: EcsVTable,
1400
1401    tx_cmd: CommandSender,
1402    rx_cmd: Rc<CommandReceiver>,
1403}
1404
1405impl<W, S> EcsApp<W, S>
1406where
1407    W: Work + 'static,
1408    S: BuildHasher + Default + 'static,
1409{
1410    /// Creates an ECS instance with the given workers, group information, and
1411    /// hasher builder type.
1412    ///
1413    /// # Examples
1414    ///
1415    /// ```
1416    /// use my_ecs::prelude::*;
1417    /// use std::hash::{BuildHasher, DefaultHasher};
1418    ///
1419    /// // Something like `std::hash::RandomState`.
1420    /// #[derive(Default)]
1421    /// struct FixedState;
1422    /// impl BuildHasher for FixedState {
1423    ///     type Hasher = DefaultHasher;
1424    ///     fn build_hasher(&self) -> Self::Hasher {
1425    ///         DefaultHasher::new()
1426    ///     }
1427    /// }
1428    ///
1429    /// // Creates `EcsApp` with one group consisting of 4 workers.
1430    /// let pool = WorkerPool::with_len(4);
1431    /// let ecs: EcsApp<_, FixedState> = EcsApp::new(pool.into(), &[4]);
1432    ///
1433    /// // Creates `EcsApp` with two groups consisting of 2 workers respectively.
1434    /// let pool = WorkerPool::with_len(4);
1435    /// let ecs: EcsApp<_, FixedState> = EcsApp::new(pool.into(), &[2, 2]);
1436    /// ```
1437    pub fn new(workers: Vec<W>, groups: &[usize]) -> Self {
1438        // We need a group even if it's empty for now.
1439        let groups = if groups.is_empty() { &[0][..] } else { groups };
1440
1441        let (tx_cmd, rx_cmd) = command_channel(thread::current());
1442        let rx_cmd = Rc::new(rx_cmd);
1443        let sched = Scheduler::new(workers, groups, tx_cmd.clone(), Rc::clone(&rx_cmd));
1444
1445        let mut this = Self {
1446            sys_stor: SystemStorage::new(groups.len()),
1447            ent_stor: EntityStorage::new(),
1448            res_stor: ResourceStorage::new(),
1449            cache_stor: CacheStorage::new(),
1450            sched,
1451            cmd_errs: Vec::new(),
1452            vtable: EcsVTable::new::<W, S>(),
1453            tx_cmd: tx_cmd.clone(),
1454            rx_cmd,
1455        };
1456
1457        // Registers a `Post` resource.
1458        let tx_msg = this.sched.get_send_message_queue().clone();
1459        let fut_cnt = Arc::clone(this.sched.get_future_count());
1460        let tx_dedi = this.sched.get_tx_dedi_queue().clone();
1461        let post = Post::new(tx_cmd, tx_msg, tx_dedi, fut_cnt);
1462        this.add_resource(post).unwrap();
1463
1464        this
1465    }
1466
1467    /// Destroys the ecs instance and returns workers.
1468    pub fn destroy(mut self) -> Vec<W> {
1469        // Remaining commands and systems must be cancelled.
1470        self.clear_command();
1471        self.clear_system();
1472
1473        // Takes workers out from the scheduler.
1474        let tx_cmd = self.tx_cmd.clone();
1475        let rx_cmd = Rc::clone(&self.rx_cmd);
1476        let old = mem::replace(
1477            &mut self.sched,
1478            Scheduler::new(Vec::new(), &[], tx_cmd, rx_cmd),
1479        );
1480        old.take_workers()
1481    }
1482
1483    /// Takes out poisoned systems so far.
1484    ///
1485    /// # Examples
1486    ///
1487    /// ```
1488    /// use my_ecs::prelude::*;
1489    ///
1490    /// let v = Ecs::default(WorkerPool::with_len(1), [1])
1491    ///     .add_once_system(|| {
1492    ///         panic!("panics on purpose");
1493    ///     })
1494    ///     .step()
1495    ///     .collect_poisoned_systems();
1496    /// assert_eq!(v.len(), 1);
1497    /// ```
1498    pub fn collect_poisoned_systems(&mut self) -> Vec<PoisonedSystem> {
1499        self.sys_stor.drain_poisoned().collect()
1500    }
1501
1502    /// Shrinks the capacity of internal data structures as much as possible.
1503    pub fn shrink_to_fit(&mut self) {
1504        let post = self.get_resource::<Post>().unwrap();
1505        post.shrink_to_fit();
1506        // TODO: need more shrink methods.
1507    }
1508
1509    /// Executes active systems of all groups once.
1510    ///
1511    /// Generated commands during the execution will be completely consumed at
1512    /// the end of system execution.
1513    ///
1514    /// # Examples
1515    ///
1516    /// ```
1517    /// use my_ecs::prelude::*;
1518    /// use std::sync::{Arc, Mutex};
1519    ///
1520    /// let cnt = Arc::new(Mutex::new(0));
1521    /// let c_cnt = Arc::clone(&cnt);
1522    ///
1523    /// Ecs::default(WorkerPool::new(), [])
1524    ///     .add_system(move || {
1525    ///         *c_cnt.lock().unwrap() += 1;
1526    ///     })
1527    ///     .step();
1528    /// assert_eq!(*cnt.lock().unwrap(), 1);
1529    /// ```
1530    pub fn step(&mut self) -> &mut Self {
1531        self._step();
1532        self
1533    }
1534
1535    /// Returns whether commands were executed at this cycle.
1536    fn _step(&mut self) -> bool {
1537        // Executes.
1538        let sgroups = &mut self.sys_stor.sgroups;
1539        let mut cache =
1540            RefreshCacheStorage::new(&mut self.cache_stor, &mut self.ent_stor, &mut self.res_stor);
1541        self.sched.execute_all(sgroups, &mut cache);
1542
1543        // Consumes buffered commands.
1544        let run_cmd = self.process_buffered_commands();
1545
1546        // Clears dead systems caused by the execution above.
1547        self.clear_dead_system();
1548
1549        run_cmd
1550    }
1551
1552    /// Executes active systems of all groups until their lifetime goes to zero.
1553    ///
1554    /// # Examples
1555    ///
1556    /// ```
1557    /// use my_ecs::prelude::*;
1558    /// use std::sync::{Arc, Mutex};
1559    ///
1560    /// let cnt = Arc::new(Mutex::new(0));
1561    /// let c_cnt = Arc::clone(&cnt);
1562    ///
1563    /// Ecs::default(WorkerPool::new(), [])
1564    ///     .add_system(
1565    ///         SystemDesc::new()
1566    ///             .with_activation(2, InsertPos::Back)
1567    ///             .with_system(move || {
1568    ///                 *c_cnt.lock().unwrap() += 1;
1569    ///             })
1570    ///     )
1571    ///     .run(|_| {});
1572    /// assert_eq!(*cnt.lock().unwrap(), 2);
1573    /// ```
1574    pub fn run<F, R>(&mut self, mut handle_error: F) -> With<&mut Self, Vec<R>>
1575    where
1576        F: FnMut(Box<dyn Error + Send + Sync + 'static>) -> R,
1577    {
1578        debug_assert_eq!(self.sched.num_groups(), self.sys_stor.num_groups());
1579
1580        let mut ret = Vec::new();
1581
1582        loop {
1583            let run_cmd = self._step();
1584            let is_completed = self.wait_for_idle().is_completed();
1585
1586            for err in self.errors() {
1587                ret.push(handle_error(err));
1588            }
1589
1590            if is_completed {
1591                break;
1592            }
1593
1594            // * We've run commands: new active systems could be inserted. We
1595            //   need to go to the next cycle.
1596            // * No commands & remaining dedicated futures: Waits for the
1597            //   remaining futures to send tasks in order to avoid busy-waiting.
1598            if !run_cmd && self.sched.has_dedicated_future() {
1599                self.sched.wait_receiving_dedicated_task();
1600            }
1601        }
1602
1603        With::new(self, ret)
1604    }
1605
1606    /// Waits for ecs to be idle.
1607    ///
1608    /// Ecs becomes `idle` when all group's workers get closed.
1609    pub fn wait_for_idle(&mut self) -> &mut Self {
1610        self.sched.wait_exhausted();
1611        self
1612    }
1613
1614    /// Determines whether ecs has been executed completely, so that it cannot
1615    /// do anything.
1616    ///
1617    /// If all conditions below are met, then ecs is considered as completed.
1618    /// - No active systems
1619    /// - No uncompleted commands
1620    /// - No open sub workers
1621    pub fn is_completed(&self) -> bool {
1622        // For main worker, no active systems?
1623        let no_active = self
1624            .sys_stor
1625            .sgroups
1626            .iter()
1627            .all(|sgroup| sgroup.len_active() == 0);
1628
1629        // For main worker, no uncompleted commands?
1630        let no_cmd = !self.sched.has_command();
1631
1632        // For main worker, no remaining async tasks?
1633        let no_fut = !self.sched.has_dedicated_future();
1634
1635        // For sub workers, they are closed?
1636        let is_sub_exhausted = self.sched.is_work_groups_exhausted();
1637
1638        is_sub_exhausted && no_active && no_cmd && no_fut
1639    }
1640
1641    // TODO: doc example to test downcast error
1642    // error: EcsError<SystemData>
1643    fn register_system_inner(
1644        &mut self,
1645        mut sdata: SystemData,
1646        group_index: u16,
1647        volatile: bool,
1648        private: bool,
1649    ) -> Result<SystemId, EcsError<SystemData>> {
1650        if let Err(e) = validate_request::<W, S>(self, &sdata) {
1651            return Err(e.with_data(sdata));
1652        }
1653        complete_data::<W, S>(self, &mut sdata, group_index, private);
1654        let sid = sdata.id();
1655        return self.sys_stor.register(sdata, volatile).map(|()| sid);
1656
1657        // === Internal helper functions ===
1658
1659        fn validate_request<W, S>(this: &EcsApp<W, S>, sdata: &SystemData) -> Result<(), EcsError>
1660        where
1661            W: Work + 'static,
1662            S: BuildHasher + Default + 'static,
1663        {
1664            // Validation procedure is as follows.
1665            // 1. Validates `Read`, `Write`, `ResRead`, `ResWrite`, and `EntWrite`.
1666            // 2. Validates if queried resources exist.
1667            //    When it comes to resource queries, in contrast to component or
1668            //    entity queries, they must be known at the time of system
1669            //    registration. Assume that clients forgot to register required
1670            //    resources. Then, we can't give them to systems. But about
1671            //    components or entities, we can give empty iterator somehow.
1672            // 3. `EntWrite` must not overlap both `Read` and `Write`.
1673
1674            // 1. Validates request's `Read`, `Write`, `ResRead`, `ResWrite`,
1675            // and `EntWrite` themselves.
1676            let rinfo = sdata.get_request_info();
1677            if let Err(reason) = rinfo.validate() {
1678                return Err(EcsError::InvalidRequest(reason, ()));
1679            }
1680
1681            // 2. Tests if we can find queries resources now.
1682            for rkey in rinfo.resource_keys() {
1683                if !this.res_stor.contains(rkey) {
1684                    let reason = debug_format!("failed to find a resource `{:?}`", rkey);
1685                    return Err(EcsError::UnknownResource(reason, ()));
1686                }
1687            }
1688
1689            // 3. `EntWrite` must not overlap both `Read` and `Write`.
1690            let r_sinfos = rinfo.read().1.select_infos();
1691            let w_sinfos = rinfo.write().1.select_infos();
1692            for (sinfo, finfo) in r_sinfos
1693                .chain(w_sinfos)
1694                .flat_map(|sinfo| rinfo.filters().iter().map(move |(_, finfo)| (sinfo, finfo)))
1695            {
1696                if !sinfo.is_disjoint2(finfo) {
1697                    let reason = debug_format!(
1698                        "{} contains conflicting queries: {}, {}",
1699                        rinfo.name(),
1700                        sinfo.name(),
1701                        finfo.name(),
1702                    );
1703                    return Err(EcsError::InvalidRequest(reason, ()));
1704                }
1705            }
1706
1707            Ok(())
1708        }
1709
1710        fn complete_data<W, S>(
1711            this: &mut EcsApp<W, S>,
1712            sdata: &mut SystemData,
1713            group_index: u16,
1714            private: bool,
1715        ) where
1716            W: Work + 'static,
1717            S: BuildHasher + Default + 'static,
1718        {
1719            // Completes system id.
1720            debug_assert!(sdata.id().is_dummy());
1721            {
1722                let sid = this
1723                    .sys_stor
1724                    .get_group_mut(group_index as usize)
1725                    .next_system_id();
1726                sdata.set_id(sid);
1727            }
1728
1729            // Completes system flags.
1730            debug_assert!(sdata.flags().is_dedi_empty() && sdata.flags().is_private_empty());
1731            {
1732                let mut sflags = SystemFlags::empty();
1733
1734                // Is dedicated system?
1735                let res_read = &sdata.get_request_info().res_read().1;
1736                let res_write = &sdata.get_request_info().res_write().1;
1737                if res_read
1738                    .resource_keys()
1739                    .iter()
1740                    .chain(res_write.resource_keys())
1741                    .any(|rkey| this.res_stor.is_dedicated2(rkey).unwrap())
1742                {
1743                    sflags |= SystemFlags::DEDI_SET;
1744                } else {
1745                    sflags |= SystemFlags::DEDI_RESET;
1746                }
1747
1748                // Is private system?
1749                if private {
1750                    sflags |= SystemFlags::PRIVATE_SET;
1751                } else {
1752                    sflags |= SystemFlags::PRIVATE_RESET;
1753                }
1754
1755                // If the app doesn't have sub workers, makes the system dedicated.
1756                debug_assert_eq!(this.sched.num_groups(), this.sys_stor.num_groups());
1757                if this.sched.num_workers() == 0 {
1758                    sflags |= SystemFlags::DEDI_SET;
1759                }
1760
1761                sdata.union_flags(sflags);
1762            }
1763        }
1764    }
1765
1766    fn unregister_system_inner(&mut self, sid: &SystemId) -> Result<(), EcsError> {
1767        self.sys_stor.unregister(sid)
1768    }
1769
1770    fn activate_system_inner(
1771        &mut self,
1772        target: SystemId,
1773        at: InsertPos,
1774        live: Tick,
1775    ) -> Result<(), EcsError> {
1776        // Activates the system.
1777        self.sys_stor.activate(&target, at, live)?;
1778
1779        // Refreshes cache item for the system.
1780        let sgroup = self.sys_stor.get_group_mut(target.group_index() as usize);
1781        // Safety: The system was successfully activated, so we definitely can
1782        // get the system data.
1783        let sdata = unsafe { sgroup.get_active(&target).unwrap_unchecked() };
1784        self.cache_stor.remove_item(target);
1785        self.cache_stor
1786            .create_item(sdata, &mut self.ent_stor, &mut self.res_stor);
1787        Ok(())
1788    }
1789
1790    fn inactivate_system_inner(&mut self, sid: &SystemId) -> Result<(), EcsError> {
1791        self.sys_stor.inactivate(sid)
1792    }
1793
1794    fn register_entity_inner(&mut self, desc: EntityReg) -> Result<EntityIndex, EcsError> {
1795        // Registers entity.
1796        let ei = self.ent_stor.register(desc)?;
1797        let ekey = EntityKeyRef::Index(&ei);
1798        self.cache_stor
1799            .update_by_entity_reg(ekey, &mut self.ent_stor, &mut self.res_stor);
1800
1801        // Makes wait queue for the entity.
1802        let cont = unsafe { self.ent_stor.get_entity_container(ekey).unwrap_unchecked() };
1803        self.sched
1804            .get_wait_queues_mut()
1805            .initialize_entity_queue(ei.index(), cont.num_columns());
1806
1807        Ok(ei)
1808    }
1809
1810    fn unregister_entity_inner(
1811        &mut self,
1812        ekey: EntityKeyRef<'_>,
1813    ) -> Result<Box<dyn ContainEntity>, EcsError> {
1814        if self.ent_stor.get_entity_container(ekey).is_none() {
1815            let reason = debug_format!("failed to find an entity `{:?}`", ekey);
1816            return Err(EcsError::UnknownEntity(reason, ()));
1817        }
1818
1819        // We must update cache before we unregister ent entity.
1820        self.cache_stor
1821            .update_by_entity_unreg(ekey, &mut self.ent_stor, &mut self.res_stor);
1822
1823        let (_, cont) = self.ent_stor.unregister(ekey).unwrap();
1824        Ok(cont.into_inner())
1825    }
1826
1827    fn add_resource_inner(
1828        &mut self,
1829        desc: ResourceDesc,
1830    ) -> Result<ResourceIndex, EcsError<ResourceDesc>> {
1831        let ri = self.res_stor.add(desc)?;
1832        self.sched
1833            .get_wait_queues_mut()
1834            .initialize_resource_queue(ri.index());
1835        Ok(ri)
1836    }
1837
1838    fn remove_resource_inner(
1839        &mut self,
1840        rkey: &ResourceKey,
1841    ) -> Result<Option<Box<dyn Any>>, EcsError> {
1842        self.cache_stor
1843            .update_by_resource_unreg(rkey, |sid: &SystemId| {
1844                self.sys_stor.inactivate(sid).unwrap()
1845            });
1846        match self.res_stor.remove(rkey) {
1847            Some(Or::A(owned)) => Ok(Some(owned)),
1848            Some(Or::B(_ptr)) => Ok(None),
1849            None => {
1850                let reason = debug_format!("failed to find a resource `{:?}`", rkey);
1851                Err(EcsError::UnknownResource(reason, ()))
1852            }
1853        }
1854    }
1855
1856    fn get_resource_inner(&self, rkey: &ResourceKey) -> Option<NonNull<u8>> {
1857        match self.res_stor.borrow2(rkey) {
1858            // If it is borrowed successfully, we can replace `Borrowed` with
1859            // shared reference.
1860            Ok(borrowed) => Some(borrowed.as_nonnull()),
1861            Err(..) => None,
1862        }
1863    }
1864
1865    fn get_resource_mut_inner(&mut self, rkey: &ResourceKey) -> Option<NonNull<u8>> {
1866        match self.res_stor.borrow_mut2(rkey) {
1867            // If it is borrowed successfully, we can replace `Borrowed` with
1868            // mutable reference.
1869            Ok(borrowed) => Some(borrowed.as_nonnull()),
1870            Err(..) => None,
1871        }
1872    }
1873
1874    fn get_resource_index_inner(&self, rkey: &ResourceKey) -> Option<ResourceIndex> {
1875        self.res_stor.index(rkey)
1876    }
1877
1878    fn process_buffered_commands(&mut self) -> bool {
1879        let mut run_cmd = false;
1880
1881        while let Ok(cmd) = self.rx_cmd.try_recv() {
1882            let ecs = Ecs::new(self);
1883            match cmd.command(ecs) {
1884                Ok(()) => {}
1885                Err(err) => self.cmd_errs.push(err),
1886            }
1887
1888            run_cmd = true;
1889        }
1890
1891        run_cmd
1892    }
1893
1894    /// Cancels out remaining commands.
1895    ///
1896    /// Commands are functions that can be executed or cancelled. They can be
1897    /// cancelled by getting called [`cancel`].
1898    ///
1899    /// [`cancel`]: Command::cancel
1900    fn clear_command(&mut self) {
1901        // Blocks more commands.
1902        self.rx_cmd.close();
1903
1904        // Cancels out all buffered commands.
1905        while let Ok(cmd) = self.rx_cmd.try_recv() {
1906            cmd.cancel();
1907        }
1908    }
1909
1910    /// Cancels out remaining systems.
1911    ///
1912    /// Systems are functions that can be executed or cancelled. They can be
1913    /// cancelled by becoming [`SystemState::Dead`] states.
1914    ///
1915    /// [`SystemState::Dead`]: crate::ecs::sys::system::SystemState::Dead
1916    fn clear_system(&mut self) {
1917        let num_groups = self.sys_stor.num_groups();
1918        for gi in 0..num_groups {
1919            self.sys_stor.get_group_mut(gi).clear();
1920        }
1921    }
1922
1923    /// Clears dead systems with their cache items.
1924    fn clear_dead_system(&mut self) {
1925        for sdata in self.sys_stor.drain_dead() {
1926            self.cache_stor.remove_item(sdata.id());
1927        }
1928    }
1929
1930    fn get_entity_container_mut<'r, K>(&mut self, ekey: K) -> Option<&mut EntityContainer>
1931    where
1932        K: Into<EntityKeyRef<'r>>,
1933    {
1934        self.ent_stor.get_entity_container_mut(ekey)
1935    }
1936}
1937
1938impl<W, S> EcsEntry for EcsApp<W, S>
1939where
1940    W: Work + 'static,
1941    S: BuildHasher + Default + 'static,
1942{
1943    fn add_system<T, Sys>(
1944        &mut self,
1945        desc: T,
1946    ) -> WithResult<&mut Self, SystemId, EcsError<SystemDesc<Sys>>>
1947    where
1948        T: Into<SystemDesc<Sys>>,
1949        Sys: System,
1950    {
1951        let res = Ecs::new(self).add_system(desc).take();
1952        WithResult::new(self, res)
1953    }
1954
1955    fn add_once_system<T, Req, F>(
1956        &mut self,
1957        sys: T,
1958    ) -> WithResult<&mut Self, SystemId, EcsError<SystemDesc<FnOnceSystem<Req, F>>>>
1959    where
1960        T: Into<FnOnceSystem<Req, F>>,
1961        FnOnceSystem<Req, F>: System,
1962    {
1963        let res = Ecs::new(self).add_once_system(sys).take();
1964        WithResult::new(self, res)
1965    }
1966
1967    fn unregister_system(&mut self, sid: SystemId) -> WithResult<&mut Self, (), EcsError> {
1968        let res = Ecs::new(self).unregister_system(sid).take();
1969        WithResult::new(self, res)
1970    }
1971
1972    fn activate_system(
1973        &mut self,
1974        target: SystemId,
1975        at: InsertPos,
1976        live: Tick,
1977    ) -> WithResult<&mut Self, (), EcsError> {
1978        let res = Ecs::new(self).activate_system(target, at, live).take();
1979        WithResult::new(self, res)
1980    }
1981
1982    fn inactivate_system(&mut self, sid: SystemId) -> WithResult<&mut Self, (), EcsError> {
1983        let res = Ecs::new(self).inactivate_system(sid).take();
1984        WithResult::new(self, res)
1985    }
1986
1987    fn register_entity(&mut self, desc: EntityReg) -> WithResult<&mut Self, EntityIndex, EcsError> {
1988        let res = Ecs::new(self).register_entity(desc).take();
1989        WithResult::new(self, res)
1990    }
1991
1992    fn unregister_entity<C>(&mut self) -> WithResult<&mut Self, Box<dyn ContainEntity>, EcsError>
1993    where
1994        C: Components,
1995    {
1996        let res = Ecs::new(self).unregister_entity::<C>().take();
1997        WithResult::new(self, res)
1998    }
1999
2000    fn add_entity<E>(
2001        &mut self,
2002        ei: EntityIndex,
2003        value: E,
2004    ) -> WithResult<&mut Self, EntityId, EcsError<E>>
2005    where
2006        E: Entity,
2007    {
2008        let res = Ecs::new(self).add_entity(ei, value).take();
2009        WithResult::new(self, res)
2010    }
2011
2012    fn remove_entity(&mut self, eid: EntityId) -> WithResult<&mut Self, (), EcsError> {
2013        let res = Ecs::new(self).remove_entity(eid).take();
2014        WithResult::new(self, res)
2015    }
2016
2017    fn add_resource<T>(
2018        &mut self,
2019        desc: T,
2020    ) -> WithResult<&mut Self, ResourceIndex, EcsError<ResourceDesc>>
2021    where
2022        T: Into<ResourceDesc>,
2023    {
2024        let res = Ecs::new(self).add_resource(desc).take();
2025        WithResult::new(self, res)
2026    }
2027
2028    fn remove_resource<R>(&mut self) -> WithResult<&mut Self, Option<R>, EcsError>
2029    where
2030        R: Resource,
2031    {
2032        let res = Ecs::new(self).remove_resource::<R>().take();
2033        WithResult::new(self, res)
2034    }
2035
2036    fn get_resource<R>(&self) -> Option<&R>
2037    where
2038        R: Resource,
2039    {
2040        self.get_resource_inner(&R::key())
2041            .map(|ptr| unsafe { ptr.cast::<R>().as_ref() })
2042    }
2043
2044    fn get_resource_mut<R>(&mut self) -> Option<&mut R>
2045    where
2046        R: Resource,
2047    {
2048        self.get_resource_mut_inner(&R::key())
2049            .map(|ptr| unsafe { ptr.cast::<R>().as_mut() })
2050    }
2051
2052    fn get_resource_index<R>(&self) -> Option<ResourceIndex>
2053    where
2054        R: Resource,
2055    {
2056        self.get_resource_index_inner(&R::key())
2057    }
2058
2059    fn execute_commands<T>(
2060        &mut self,
2061        cmds: T,
2062    ) -> WithResult<&mut Self, (), Box<dyn Error + Send + Sync + 'static>>
2063    where
2064        T: HelpExecuteManyCommands,
2065    {
2066        let res = Ecs::new(self).execute_commands(cmds).take();
2067        WithResult::new(self, res)
2068    }
2069
2070    fn execute_command<F, R>(
2071        &mut self,
2072        f: F,
2073    ) -> WithResult<&mut Self, (), Box<dyn Error + Send + Sync + 'static>>
2074    where
2075        F: FnOnce(Commander) -> R,
2076        R: Command,
2077    {
2078        let res = Ecs::new(self).execute_command(f).take();
2079        WithResult::new(self, res)
2080    }
2081
2082    fn errors(&mut self) -> Vec<Box<dyn Error + Send + Sync + 'static>> {
2083        mem::take(&mut self.cmd_errs)
2084    }
2085}
2086
2087impl<W, S> Drop for EcsApp<W, S>
2088where
2089    W: Work + 'static,
2090    S: BuildHasher + Default + 'static,
2091{
2092    fn drop(&mut self) {
2093        self.clear_command();
2094        self.clear_system();
2095    }
2096}
2097
2098impl<W, S> Resource for EcsApp<W, S>
2099where
2100    EcsApp<W, S>: Send + 'static,
2101    W: Work + 'static,
2102    S: BuildHasher + Default + 'static,
2103{
2104}
2105
2106impl<W, S> From<EcsApp<W, S>> for LeakedEcsApp
2107where
2108    W: Work + 'static,
2109    S: BuildHasher + Default + 'static,
2110{
2111    fn from(value: EcsApp<W, S>) -> Self {
2112        LeakedEcsApp::new(value)
2113    }
2114}
2115
2116/// A handle to an [`EcsApp`].
2117///
2118/// This is useful when you need to move the ECS instance onto heap memory from
2119/// stack, then have ownership by its handle. Because this type deals with the
2120/// ownership, this is non-cloneable. When the handle is dropped, associated ECS
2121/// instance is also dropepd and deallocated from heap memory.
2122///
2123/// You can use [`From`] to convert `EcsApp` into this handle.
2124pub struct LeakedEcsApp {
2125    this: Ecs<'static>,
2126    drop: unsafe fn(Ecs<'static>),
2127}
2128
2129impl LeakedEcsApp {
2130    fn new<W, S>(app: EcsApp<W, S>) -> Self
2131    where
2132        W: Work + 'static,
2133        S: BuildHasher + Default + 'static,
2134    {
2135        unsafe fn _drop<W, S>(ecs: Ecs<'static>)
2136        where
2137            W: Work + 'static,
2138            S: BuildHasher + Default + 'static,
2139        {
2140            let ptr = ecs.this.cast::<EcsApp<W, S>>();
2141            let boxed_ecs = unsafe { Box::from_raw(ptr.as_ptr()) };
2142            drop(boxed_ecs);
2143        }
2144
2145        Self {
2146            this: Ecs::new(Box::leak(Box::new(app))),
2147            drop: _drop::<W, S>,
2148        }
2149    }
2150
2151    /// # Safety
2152    ///
2153    /// See [`Ecs::copy`].
2154    #[cfg(target_arch = "wasm32")]
2155    pub(crate) unsafe fn get(&self) -> EcsExt<'static> {
2156        EcsExt {
2157            ecs: self.this.copy(),
2158        }
2159    }
2160}
2161
2162impl Drop for LeakedEcsApp {
2163    fn drop(&mut self) {
2164        // Safety:
2165        // - `self.drop` holds proper drop method for `self.this`
2166        // - It cannot be double free because we release `self.this` here only.
2167        // See `Self::new()` for more details.
2168        unsafe { (self.drop)(self.this.copy()) };
2169    }
2170}
2171
2172impl Deref for LeakedEcsApp {
2173    type Target = Ecs<'static>;
2174
2175    fn deref(&self) -> &Self::Target {
2176        &self.this
2177    }
2178}
2179
2180impl DerefMut for LeakedEcsApp {
2181    fn deref_mut(&mut self) -> &mut Self::Target {
2182        &mut self.this
2183    }
2184}
2185
2186/// Extended [`Ecs`] with additional methods.
2187#[repr(transparent)]
2188pub struct EcsExt<'ecs> {
2189    ecs: Ecs<'ecs>,
2190}
2191
2192impl EcsExt<'_> {
2193    /// Executes active systems of all groups once.
2194    ///
2195    /// Generated commands during the execution will be completely consumed at
2196    /// the end of system execution.
2197    pub fn step(&mut self) {
2198        unsafe {
2199            let vtable = self.ecs.vtable.as_ref();
2200            (vtable.step)(self.ecs.this);
2201        }
2202    }
2203}
2204
2205impl EcsEntry for EcsExt<'_> {
2206    fn add_system<T, Sys>(
2207        &mut self,
2208        desc: T,
2209    ) -> WithResult<&mut Self, SystemId, EcsError<SystemDesc<Sys>>>
2210    where
2211        T: Into<SystemDesc<Sys>>,
2212        Sys: System,
2213    {
2214        let res = self.ecs.add_system(desc).take();
2215        WithResult::new(self, res)
2216    }
2217
2218    fn add_once_system<T, Req, F>(
2219        &mut self,
2220        sys: T,
2221    ) -> WithResult<&mut Self, SystemId, EcsError<SystemDesc<FnOnceSystem<Req, F>>>>
2222    where
2223        T: Into<FnOnceSystem<Req, F>>,
2224        FnOnceSystem<Req, F>: System,
2225    {
2226        let res = self.ecs.add_once_system(sys).take();
2227        WithResult::new(self, res)
2228    }
2229
2230    fn unregister_system(&mut self, sid: SystemId) -> WithResult<&mut Self, (), EcsError> {
2231        let res = self.ecs.unregister_system(sid).take();
2232        WithResult::new(self, res)
2233    }
2234
2235    fn activate_system(
2236        &mut self,
2237        target: SystemId,
2238        at: InsertPos,
2239        live: Tick,
2240    ) -> WithResult<&mut Self, (), EcsError> {
2241        let res = self.ecs.activate_system(target, at, live).take();
2242        WithResult::new(self, res)
2243    }
2244
2245    fn inactivate_system(&mut self, sid: SystemId) -> WithResult<&mut Self, (), EcsError> {
2246        let res = self.ecs.inactivate_system(sid).take();
2247        WithResult::new(self, res)
2248    }
2249
2250    fn register_entity(&mut self, desc: EntityReg) -> WithResult<&mut Self, EntityIndex, EcsError> {
2251        let res = self.ecs.register_entity(desc).take();
2252        WithResult::new(self, res)
2253    }
2254
2255    fn unregister_entity<C>(&mut self) -> WithResult<&mut Self, Box<dyn ContainEntity>, EcsError>
2256    where
2257        C: Components,
2258    {
2259        let res = self.ecs.unregister_entity::<C>().take();
2260        WithResult::new(self, res)
2261    }
2262
2263    fn add_entity<E>(
2264        &mut self,
2265        ei: EntityIndex,
2266        value: E,
2267    ) -> WithResult<&mut Self, EntityId, EcsError<E>>
2268    where
2269        E: Entity,
2270    {
2271        let res = self.ecs.add_entity(ei, value).take();
2272        WithResult::new(self, res)
2273    }
2274
2275    fn remove_entity(&mut self, eid: EntityId) -> WithResult<&mut Self, (), EcsError> {
2276        let res = self.ecs.remove_entity(eid).take();
2277        WithResult::new(self, res)
2278    }
2279
2280    fn add_resource<T>(
2281        &mut self,
2282        desc: T,
2283    ) -> WithResult<&mut Self, ResourceIndex, EcsError<ResourceDesc>>
2284    where
2285        T: Into<ResourceDesc>,
2286    {
2287        let res = self.ecs.add_resource(desc).take();
2288        WithResult::new(self, res)
2289    }
2290
2291    fn remove_resource<R>(&mut self) -> WithResult<&mut Self, Option<R>, EcsError>
2292    where
2293        R: Resource,
2294    {
2295        let res = self.ecs.remove_resource::<R>().take();
2296        WithResult::new(self, res)
2297    }
2298
2299    fn get_resource<R>(&self) -> Option<&R>
2300    where
2301        R: Resource,
2302    {
2303        self.ecs.get_resource()
2304    }
2305
2306    fn get_resource_mut<R>(&mut self) -> Option<&mut R>
2307    where
2308        R: Resource,
2309    {
2310        self.ecs.get_resource_mut()
2311    }
2312
2313    fn get_resource_index<R>(&self) -> Option<ResourceIndex>
2314    where
2315        R: Resource,
2316    {
2317        self.ecs.get_resource_index::<R>()
2318    }
2319
2320    fn execute_commands<T>(
2321        &mut self,
2322        cmds: T,
2323    ) -> WithResult<&mut Self, (), Box<dyn Error + Send + Sync + 'static>>
2324    where
2325        T: HelpExecuteManyCommands,
2326    {
2327        let res = self.ecs.execute_commands(cmds).take();
2328        WithResult::new(self, res)
2329    }
2330
2331    fn execute_command<F, R>(
2332        &mut self,
2333        f: F,
2334    ) -> WithResult<&mut Self, (), Box<dyn Error + Send + Sync + 'static>>
2335    where
2336        F: FnOnce(Commander) -> R,
2337        R: Command,
2338    {
2339        let res = self.ecs.execute_command(f).take();
2340        WithResult::new(self, res)
2341    }
2342
2343    fn errors(&mut self) -> Vec<Box<dyn Error + Send + Sync + 'static>> {
2344        self.ecs.errors()
2345    }
2346}
2347
2348#[cfg(test)]
2349mod tests {
2350    use crate as my_ecs;
2351    use crate::prelude::*;
2352    use std::sync::{Arc, Mutex};
2353
2354    #[test]
2355    fn test_add_many_systems() {
2356        let mut ecs = Ecs::default(WorkerPool::with_len(1), [1]);
2357
2358        let state = Arc::new(Mutex::new(vec![]));
2359
2360        // Declares a system.
2361        struct StructSystem(Arc<Mutex<Vec<i32>>>);
2362        request!(Req);
2363        impl System for StructSystem {
2364            type Request = Req;
2365            fn run(&mut self, _resp: Response<'_, Self::Request>) {
2366                self.0.lock().unwrap().push(0);
2367            }
2368        }
2369        let sys0 = StructSystem(Arc::clone(&state));
2370
2371        // Declares a system.
2372        let c_state = Arc::clone(&state);
2373        let sys1 = move || {
2374            c_state.lock().unwrap().push(1);
2375        };
2376
2377        ecs.add_systems((sys0, sys1)).step();
2378
2379        assert_eq!(*state.lock().unwrap(), vec![0, 1]);
2380    }
2381
2382    #[test]
2383    fn test_execute_many_commands() {
2384        let mut ecs = Ecs::default(WorkerPool::with_len(1), [1]);
2385
2386        let state = Arc::new(Mutex::new(vec![]));
2387
2388        // Declares a command.
2389        struct StructCommand(Arc<Mutex<Vec<i32>>>);
2390        impl Command for StructCommand {
2391            fn command(&mut self, _ecs: Ecs<'_>) -> DynResult<()> {
2392                self.0.lock().unwrap().push(0);
2393                Ok(())
2394            }
2395        }
2396        let cmd0 = StructCommand(Arc::clone(&state));
2397
2398        // Declares a command.
2399        let c_state = Arc::clone(&state);
2400        let cmd1 = move |_ecs: Ecs| {
2401            c_state.lock().unwrap().push(1);
2402            Ok(())
2403        };
2404
2405        ecs.execute_commands((cmd0, Some(cmd1))).unwrap();
2406
2407        assert_eq!(*state.lock().unwrap(), vec![0, 1]);
2408    }
2409
2410    #[test]
2411    fn test_add_many_resources() {
2412        use crate as my_ecs;
2413        let mut ecs = Ecs::default(WorkerPool::with_len(1), [1]);
2414
2415        // Declares a resource.
2416        #[derive(Resource)]
2417        struct Ra(i32);
2418        #[derive(Resource)]
2419        struct Rb(String);
2420
2421        let ra = Ra(0);
2422        let rb = Rb("b".to_owned());
2423        ecs.add_resources((ra, rb))
2424            .add_once_system(|rr: ResRead<(Ra, Rb)>| {
2425                let (a, b) = rr.0;
2426                assert_eq!(a.0, 0);
2427                assert_eq!(&b.0, "b");
2428            })
2429            .step();
2430
2431        assert!(ecs.collect_poisoned_systems().is_empty());
2432    }
2433
2434    #[test]
2435    fn test_zero_workers() {
2436        let cnt = Arc::new(Mutex::new(0));
2437        let cnt0 = Arc::clone(&cnt);
2438        let cnt1 = Arc::clone(&cnt);
2439
2440        Ecs::default(WorkerPool::new(), [])
2441            .add_once_systems((
2442                move || *cnt0.lock().unwrap() += 1,
2443                move || *cnt1.lock().unwrap() += 10,
2444            ))
2445            .step();
2446
2447        assert_eq!(*cnt.lock().unwrap(), 11);
2448    }
2449
2450    #[test]
2451    fn test_multiple_apps() {
2452        let mut a = Ecs::default(WorkerPool::with_len(1), [1]);
2453        let mut b = Ecs::default(WorkerPool::new(), []);
2454
2455        let cnt = Arc::new(Mutex::new(0));
2456        let cnt_a = Arc::clone(&cnt);
2457        let cnt_b = Arc::clone(&cnt);
2458
2459        a.add_once_system(move || *cnt_a.lock().unwrap() += 1)
2460            .unwrap();
2461        b.add_once_system(move || *cnt_b.lock().unwrap() += 10)
2462            .unwrap();
2463
2464        a.step();
2465        assert_eq!(*cnt.lock().unwrap(), 1);
2466        drop(a);
2467
2468        b.step();
2469        assert_eq!(*cnt.lock().unwrap(), 11);
2470        drop(b);
2471    }
2472}