1use alloc::borrow::Cow;
4use alloc::collections::BTreeSet;
5use core::alloc::Layout;
6use core::any::TypeId;
7use core::ops::Index;
8
9use ahash::RandomState;
10pub use evenio_macros::Component;
11
12use crate::archetype::{Archetype, ArchetypeIdx};
13use crate::drop::DropFn;
14use crate::entity::EntityLocation;
15use crate::event::{EventPtr, GlobalEvent, TargetedEventId};
16use crate::handler::{HandlerConfig, HandlerInfo, HandlerParam, InitError};
17use crate::map::{Entry, IndexSet, TypeIdMap};
18use crate::mutability::{Mutability, MutabilityMarker};
19use crate::prelude::World;
20use crate::slot_map::{Key, SlotMap};
21use crate::sparse::SparseIndex;
22use crate::world::UnsafeWorldCell;
23
24#[derive(Debug)]
39pub struct Components {
40 infos: SlotMap<ComponentInfo>,
41 by_type_id: TypeIdMap<ComponentId>,
42}
43
44impl Components {
45 pub(crate) fn new() -> Self {
46 Self {
47 infos: SlotMap::new(),
48 by_type_id: TypeIdMap::default(),
49 }
50 }
51
52 pub(crate) fn add(&mut self, desc: ComponentDescriptor) -> (ComponentId, bool) {
53 if let Some(type_id) = desc.type_id {
54 return match self.by_type_id.entry(type_id) {
55 Entry::Vacant(v) => {
56 let Some(k) = self.infos.insert_with(|k| ComponentInfo {
57 name: desc.name,
58 id: ComponentId(k),
59 type_id: desc.type_id,
60 layout: desc.layout,
61 drop: desc.drop,
62 mutability: desc.mutability,
63 insert_events: BTreeSet::new(),
64 remove_events: BTreeSet::new(),
65 member_of: IndexSet::with_hasher(RandomState::new()),
66 }) else {
67 panic!("too many components")
68 };
69
70 (*v.insert(ComponentId(k)), true)
71 }
72 Entry::Occupied(o) => (*o.get(), false),
73 };
74 }
75
76 let Some(k) = self.infos.insert_with(|k| ComponentInfo {
77 name: desc.name,
78 id: ComponentId(k),
79 type_id: desc.type_id,
80 layout: desc.layout,
81 drop: desc.drop,
82 mutability: desc.mutability,
83 insert_events: BTreeSet::new(),
84 remove_events: BTreeSet::new(),
85 member_of: IndexSet::with_hasher(RandomState::new()),
86 }) else {
87 panic!("too many components")
88 };
89
90 (ComponentId(k), true)
91 }
92
93 pub(crate) fn remove(&mut self, component_id: ComponentId) -> Option<ComponentInfo> {
94 let info = self.infos.remove(component_id.0)?;
95
96 if let Some(type_id) = info.type_id {
97 self.by_type_id.remove(&type_id);
98 }
99
100 Some(info)
101 }
102
103 pub fn get(&self, id: ComponentId) -> Option<&ComponentInfo> {
106 self.infos.get(id.0)
107 }
108
109 pub fn get_by_index(&self, idx: ComponentIdx) -> Option<&ComponentInfo> {
112 self.infos.get_by_index(idx.0).map(|(_, v)| v)
113 }
114
115 pub(crate) fn get_by_index_mut(&mut self, idx: ComponentIdx) -> Option<&mut ComponentInfo> {
116 self.infos.get_by_index_mut(idx.0).map(|(_, v)| v)
117 }
118
119 pub fn get_by_type_id(&self, type_id: TypeId) -> Option<&ComponentInfo> {
122 let id = *self.by_type_id.get(&type_id)?;
123 Some(unsafe { self.get(id).unwrap_unchecked() })
124 }
125
126 pub fn contains(&self, id: ComponentId) -> bool {
128 self.get(id).is_some()
129 }
130
131 pub fn iter(&self) -> impl Iterator<Item = &ComponentInfo> {
133 self.infos.iter().map(|(_, v)| v)
134 }
135}
136
137impl Index<ComponentId> for Components {
138 type Output = ComponentInfo;
139
140 fn index(&self, index: ComponentId) -> &Self::Output {
141 if let Some(info) = self.get(index) {
142 info
143 } else {
144 panic!("no such component with ID of {index:?} exists")
145 }
146 }
147}
148
149impl Index<ComponentIdx> for Components {
150 type Output = ComponentInfo;
151
152 fn index(&self, index: ComponentIdx) -> &Self::Output {
153 if let Some(info) = self.get_by_index(index) {
154 info
155 } else {
156 panic!("no such component with index of {index:?} exists")
157 }
158 }
159}
160
161impl Index<TypeId> for Components {
162 type Output = ComponentInfo;
163
164 fn index(&self, index: TypeId) -> &Self::Output {
165 if let Some(info) = self.get_by_type_id(index) {
166 info
167 } else {
168 panic!("no such component with type ID of {index:?} exists")
169 }
170 }
171}
172
173unsafe impl HandlerParam for &'_ Components {
174 type State = ();
175
176 type This<'a> = &'a Components;
177
178 fn init(_world: &mut World, _config: &mut HandlerConfig) -> Result<Self::State, InitError> {
179 Ok(())
180 }
181
182 unsafe fn get<'a>(
183 _state: &'a mut Self::State,
184 _info: &'a HandlerInfo,
185 _event_ptr: EventPtr<'a>,
186 _target_location: EntityLocation,
187 world: UnsafeWorldCell<'a>,
188 ) -> Self::This<'a> {
189 world.components()
190 }
191
192 fn refresh_archetype(_state: &mut Self::State, _arch: &Archetype) {}
193
194 fn remove_archetype(_state: &mut Self::State, _arch: &Archetype) {}
195}
196
197#[derive(Debug)]
199pub struct ComponentInfo {
200 name: Cow<'static, str>,
201 id: ComponentId,
202 type_id: Option<TypeId>,
203 layout: Layout,
204 drop: DropFn,
205 mutability: Mutability,
206 pub(crate) insert_events: BTreeSet<TargetedEventId>,
207 pub(crate) remove_events: BTreeSet<TargetedEventId>,
208 pub(crate) member_of: IndexSet<ArchetypeIdx>,
210}
211
212impl ComponentInfo {
213 pub fn name(&self) -> &str {
218 &self.name
219 }
220
221 pub fn id(&self) -> ComponentId {
223 self.id
224 }
225
226 pub fn type_id(&self) -> Option<TypeId> {
229 self.type_id
230 }
231
232 pub fn layout(&self) -> Layout {
234 self.layout
235 }
236
237 pub fn drop(&self) -> DropFn {
239 self.drop
240 }
241
242 pub fn mutability(&self) -> Mutability {
244 self.mutability
245 }
246
247 pub fn insert_events(&self) -> &BTreeSet<TargetedEventId> {
251 &self.insert_events
252 }
253
254 pub fn remove_events(&self) -> &BTreeSet<TargetedEventId> {
258 &self.remove_events
259 }
260}
261
262pub trait Component: 'static {
314 type Mutability: MutabilityMarker;
322}
323
324#[derive(Clone, Debug)]
326pub struct ComponentDescriptor {
327 pub name: Cow<'static, str>,
332 pub type_id: Option<TypeId>,
334 pub layout: Layout,
336 pub drop: DropFn,
339 pub mutability: Mutability,
341}
342
343#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
355pub struct ComponentId(Key);
356
357impl ComponentId {
358 pub const NULL: Self = Self(Key::NULL);
361
362 pub const fn new(index: u32, generation: u32) -> Option<Self> {
365 match Key::new(index, generation) {
366 Some(k) => Some(Self(k)),
367 None => None,
368 }
369 }
370
371 pub const fn index(self) -> ComponentIdx {
373 ComponentIdx(self.0.index())
374 }
375
376 pub const fn generation(self) -> u32 {
378 self.0.generation().get()
379 }
380}
381
382#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
384pub struct ComponentIdx(pub u32);
385
386unsafe impl SparseIndex for ComponentIdx {
387 const MAX: Self = Self(u32::MAX);
388
389 fn index(self) -> usize {
390 self.0.index()
391 }
392
393 fn from_index(idx: usize) -> Self {
394 Self(u32::from_index(idx))
395 }
396}
397
398#[derive(GlobalEvent, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
401pub struct AddComponent(pub ComponentId);
402
403#[derive(GlobalEvent, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
406pub struct RemoveComponent(pub ComponentId);
407
408#[cfg(test)]
409mod tests {
410 use crate::prelude::*;
411
412 #[derive(GlobalEvent)]
413 struct E;
414
415 #[test]
416 fn remove_component() {
417 #[derive(Component)]
418 struct A(String);
419
420 #[derive(Component, PartialEq, Debug)]
421 struct B(Vec<String>);
422
423 let mut world = World::new();
424
425 let c1 = world.add_component::<A>();
426 let e1 = world.spawn();
427 world.insert(e1, A("hello".into()));
428 let s1 = world.add_handler(|_: Receiver<E>, Single(A(a)): Single<&mut A>| {
429 a.push_str("hello");
430 });
431 world.send(E);
432
433 assert!(world.remove_component(c1).is_some());
434 assert!(!world.handlers().contains(s1));
435 assert!(!world.entities().contains(e1));
436 assert_eq!(
437 world.archetypes().len(),
438 1,
439 "only the empty archetype should be present"
440 );
441
442 let c2 = world.add_component::<B>();
443 let e2 = world.spawn();
444 assert!(world.entities().contains(e2));
445 world.insert(e2, B(vec![]));
446 let s2 = world.add_handler(|_: Receiver<E>, Single(B(b)): Single<&mut B>| {
447 b.push("hello".into());
448 });
449 world.send(E);
450 assert_eq!(world.get::<B>(e2), Some(&B(vec!["hello".into()])));
451
452 assert!(world.remove_component(c2).is_some());
453 assert!(!world.handlers().contains(s2));
454 assert!(!world.entities().contains(e2));
455 assert_eq!(world.archetypes().len(), 1);
456 }
457
458 #[test]
459 fn component_member_of() {
460 let mut world = World::new();
461
462 #[derive(Component)]
463 struct A;
464
465 #[derive(Component)]
466 struct B;
467
468 #[derive(Component)]
469 struct C;
470
471 let c1 = world.add_component::<A>();
472 let c2 = world.add_component::<B>();
473 let c3 = world.add_component::<C>();
474
475 let e1 = world.spawn();
476 let e2 = world.spawn();
477 let e3 = world.spawn();
478
479 world.insert(e1, A);
480
481 world.insert(e2, A);
482 world.insert(e2, B);
483
484 world.insert(e3, A);
485 world.insert(e3, B);
486 world.insert(e3, C);
487
488 assert_eq!(world.components()[c1].member_of.len(), 3);
489 assert_eq!(world.components()[c2].member_of.len(), 2);
490 assert_eq!(world.components()[c3].member_of.len(), 1);
491
492 world.remove_component(c3);
493
494 assert_eq!(world.components()[c1].member_of.len(), 2);
495 assert_eq!(world.components()[c2].member_of.len(), 1);
496
497 world.remove_component(c2);
498
499 assert_eq!(world.components()[c1].member_of.len(), 1);
500 }
501}