1use std::any::{Any, TypeId};
4use std::collections::HashMap;
5
6use crate::entity::Entity;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub struct ArchetypeId(pub(crate) u32);
15
16impl ArchetypeId {
17 pub fn index(self) -> u32 {
19 self.0
20 }
21}
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub struct EntityLocation {
30 pub archetype_id: ArchetypeId,
31 pub row: u32,
32}
33
34#[derive(Clone, Debug, PartialEq, Eq, Hash)]
43pub struct ArchetypeLayout {
44 type_ids: Vec<TypeId>,
46}
47
48impl ArchetypeLayout {
49 pub fn from_type_ids(ids: &[TypeId]) -> Self {
51 let mut sorted = ids.to_vec();
52 sorted.sort();
53 sorted.dedup();
54 Self { type_ids: sorted }
55 }
56
57 pub fn empty() -> Self {
59 Self {
60 type_ids: Vec::new(),
61 }
62 }
63
64 pub fn contains(&self, id: TypeId) -> bool {
66 self.type_ids.binary_search(&id).is_ok()
67 }
68
69 pub fn with_added(&self, id: TypeId) -> Self {
71 if self.contains(id) {
72 return self.clone();
73 }
74 let mut ids = self.type_ids.clone();
75 let pos = ids.binary_search(&id).unwrap_err();
76 ids.insert(pos, id);
77 Self { type_ids: ids }
78 }
79
80 pub fn with_removed(&self, id: TypeId) -> Self {
82 if let Ok(pos) = self.type_ids.binary_search(&id) {
83 let mut ids = self.type_ids.clone();
84 ids.remove(pos);
85 Self { type_ids: ids }
86 } else {
87 self.clone()
88 }
89 }
90
91 pub fn len(&self) -> usize {
93 self.type_ids.len()
94 }
95
96 pub fn is_empty(&self) -> bool {
98 self.type_ids.is_empty()
99 }
100
101 pub fn iter(&self) -> impl Iterator<Item = TypeId> + '_ {
103 self.type_ids.iter().copied()
104 }
105}
106
107#[allow(clippy::len_without_is_empty)]
113pub trait AnyColumn: Any + Send + Sync {
114 fn swap_remove_and_drop(&mut self, row: usize);
116
117 fn move_to(&mut self, row: usize, dst: &mut dyn AnyColumn);
120
121 fn len(&self) -> usize;
123
124 fn new_empty(&self) -> Box<dyn AnyColumn>;
126
127 fn stamp_ticks(&mut self, row: usize, added: u64, changed: u64);
129
130 fn as_any(&self) -> &dyn Any;
132 fn as_any_mut(&mut self) -> &mut dyn Any;
133}
134
135pub struct Column<T> {
140 data: Vec<T>,
141 added_ticks: Vec<u64>,
142 changed_ticks: Vec<u64>,
143}
144
145impl<T: Send + Sync + 'static> Default for Column<T> {
146 fn default() -> Self {
147 Self::new()
148 }
149}
150
151impl<T: Send + Sync + 'static> Column<T> {
152 pub fn new() -> Self {
154 Self {
155 data: Vec::new(),
156 added_ticks: Vec::new(),
157 changed_ticks: Vec::new(),
158 }
159 }
160
161 pub fn push(&mut self, value: T) {
163 self.data.push(value);
164 self.added_ticks.push(0);
165 self.changed_ticks.push(0);
166 }
167
168 pub fn push_with_ticks(&mut self, value: T, added: u64, changed: u64) {
170 self.data.push(value);
171 self.added_ticks.push(added);
172 self.changed_ticks.push(changed);
173 }
174
175 pub fn get(&self, row: usize) -> Option<&T> {
177 self.data.get(row)
178 }
179
180 pub fn get_mut(&mut self, row: usize) -> Option<&mut T> {
182 self.data.get_mut(row)
183 }
184
185 pub fn swap_remove(&mut self, row: usize) -> T {
188 self.added_ticks.swap_remove(row);
189 self.changed_ticks.swap_remove(row);
190 self.data.swap_remove(row)
191 }
192
193 pub fn len(&self) -> usize {
195 self.data.len()
196 }
197
198 pub fn is_empty(&self) -> bool {
200 self.data.is_empty()
201 }
202
203 pub fn iter(&self) -> impl Iterator<Item = &T> {
205 self.data.iter()
206 }
207
208 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
210 self.data.iter_mut()
211 }
212
213 pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
215 self.data.as_mut_ptr()
216 }
217
218 pub fn added_tick(&self, row: usize) -> u64 {
222 self.added_ticks[row]
223 }
224
225 pub fn changed_tick(&self, row: usize) -> u64 {
227 self.changed_ticks[row]
228 }
229
230 pub fn set_added_tick(&mut self, row: usize, tick: u64) {
232 self.added_ticks[row] = tick;
233 }
234
235 pub fn set_changed_tick(&mut self, row: usize, tick: u64) {
237 self.changed_ticks[row] = tick;
238 }
239
240 pub(crate) fn changed_ticks_mut_ptr(&mut self) -> *mut u64 {
242 self.changed_ticks.as_mut_ptr()
243 }
244
245 pub fn added_ticks(&self) -> &[u64] {
247 &self.added_ticks
248 }
249
250 pub fn changed_ticks(&self) -> &[u64] {
252 &self.changed_ticks
253 }
254}
255
256impl<T: Send + Sync + 'static> AnyColumn for Column<T> {
257 fn swap_remove_and_drop(&mut self, row: usize) {
258 self.data.swap_remove(row);
259 self.added_ticks.swap_remove(row);
260 self.changed_ticks.swap_remove(row);
261 }
262
263 fn move_to(&mut self, row: usize, dst: &mut dyn AnyColumn) {
264 let value = self.data.swap_remove(row);
265 let added = self.added_ticks.swap_remove(row);
266 let changed = self.changed_ticks.swap_remove(row);
267 let dst_typed = dst
268 .as_any_mut()
269 .downcast_mut::<Column<T>>()
270 .expect("move_to: column type mismatch");
271 dst_typed.data.push(value);
272 dst_typed.added_ticks.push(added);
273 dst_typed.changed_ticks.push(changed);
274 }
275
276 fn len(&self) -> usize {
277 self.data.len()
278 }
279
280 fn new_empty(&self) -> Box<dyn AnyColumn> {
281 Box::new(Column::<T>::new())
282 }
283
284 fn stamp_ticks(&mut self, row: usize, added: u64, changed: u64) {
285 self.added_ticks[row] = added;
286 self.changed_ticks[row] = changed;
287 }
288
289 fn as_any(&self) -> &dyn Any {
290 self
291 }
292
293 fn as_any_mut(&mut self) -> &mut dyn Any {
294 self
295 }
296}
297
298#[derive(Clone, Debug, Default)]
304pub struct ArchetypeEdge {
305 pub add: Option<ArchetypeId>,
307 pub remove: Option<ArchetypeId>,
309}
310
311type RequiredOptionalColumnsMut<'a, A, B> =
312 (&'a [Entity], &'a mut Column<A>, Option<&'a mut Column<B>>);
313
314type ThreeColumnsMut<'a, A, B, C> = (
315 &'a [Entity],
316 &'a mut Column<A>,
317 &'a mut Column<B>,
318 &'a mut Column<C>,
319);
320
321pub struct Archetype {
330 id: ArchetypeId,
331 layout: ArchetypeLayout,
332 entities: Vec<Entity>,
334 columns: HashMap<TypeId, Box<dyn AnyColumn>>,
336 edges: HashMap<TypeId, ArchetypeEdge>,
338}
339
340impl Archetype {
341 pub(crate) fn new(
348 id: ArchetypeId,
349 layout: ArchetypeLayout,
350 column_factories: &HashMap<TypeId, Box<dyn AnyColumn>>,
351 ) -> Self {
352 let mut columns = HashMap::new();
353 for tid in layout.iter() {
354 let template = column_factories
355 .get(&tid)
356 .unwrap_or_else(|| panic!("no column factory for {:?}", tid));
357 columns.insert(tid, template.new_empty());
358 }
359 Self {
360 id,
361 layout,
362 entities: Vec::new(),
363 columns,
364 edges: HashMap::new(),
365 }
366 }
367
368 pub fn id(&self) -> ArchetypeId {
370 self.id
371 }
372
373 pub fn layout(&self) -> &ArchetypeLayout {
375 &self.layout
376 }
377
378 pub fn len(&self) -> usize {
380 self.entities.len()
381 }
382
383 pub fn is_empty(&self) -> bool {
385 self.entities.is_empty()
386 }
387
388 pub fn entity_at(&self, row: usize) -> Entity {
390 self.entities[row]
391 }
392
393 pub fn entities(&self) -> &[Entity] {
395 &self.entities
396 }
397
398 pub fn column<T: Send + Sync + 'static>(&self) -> Option<&Column<T>> {
401 let col = self.columns.get(&TypeId::of::<T>())?;
402 col.as_any().downcast_ref::<Column<T>>()
403 }
404
405 pub fn column_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut Column<T>> {
407 let col = self.columns.get_mut(&TypeId::of::<T>())?;
408 col.as_any_mut().downcast_mut::<Column<T>>()
409 }
410
411 pub fn column_raw(&self, type_id: TypeId) -> Option<&dyn AnyColumn> {
413 self.columns.get(&type_id).map(|c| &**c)
414 }
415
416 pub fn column_raw_mut(&mut self, type_id: TypeId) -> Option<&mut dyn AnyColumn> {
418 self.columns.get_mut(&type_id).map(|c| &mut **c)
419 }
420
421 pub(crate) fn push_entity(&mut self, entity: Entity) -> u32 {
426 let row = self.entities.len() as u32;
427 self.entities.push(entity);
428 row
429 }
430
431 pub(crate) fn swap_remove_entity(&mut self, row: usize) -> (Entity, Option<Entity>) {
435 let removed = self.entities.swap_remove(row);
436 let moved = if row < self.entities.len() {
437 Some(self.entities[row])
438 } else {
439 None
440 };
441 for col in self.columns.values_mut() {
442 col.swap_remove_and_drop(row);
443 }
444 (removed, moved)
445 }
446
447 pub(crate) fn swap_remove_entity_entry(&mut self, row: usize) -> (Entity, Option<Entity>) {
452 let removed = self.entities.swap_remove(row);
453 let moved = if row < self.entities.len() {
454 Some(self.entities[row])
455 } else {
456 None
457 };
458 (removed, moved)
459 }
460
461 pub fn entities_and_column_mut<T: Send + Sync + 'static>(
465 &mut self,
466 ) -> Option<(&[Entity], &mut Column<T>)> {
467 let Self {
468 entities, columns, ..
469 } = self;
470 let col = columns.get_mut(&TypeId::of::<T>())?;
471 let col_typed = col.as_any_mut().downcast_mut::<Column<T>>()?;
472 Some((entities, col_typed))
473 }
474
475 pub fn entities_and_two_columns_mut<A, B>(
479 &mut self,
480 ) -> Option<(&[Entity], &mut Column<A>, &mut Column<B>)>
481 where
482 A: Send + Sync + 'static,
483 B: Send + Sync + 'static,
484 {
485 assert_ne!(
486 TypeId::of::<A>(),
487 TypeId::of::<B>(),
488 "cannot borrow the same column mutably twice"
489 );
490 let Self {
491 entities, columns, ..
492 } = self;
493 let ptr = columns as *mut HashMap<TypeId, Box<dyn AnyColumn>>;
494 unsafe {
501 let col_a = (*ptr)
502 .get_mut(&TypeId::of::<A>())?
503 .as_any_mut()
504 .downcast_mut::<Column<A>>()?;
505 let col_b = (*ptr)
506 .get_mut(&TypeId::of::<B>())?
507 .as_any_mut()
508 .downcast_mut::<Column<B>>()?;
509 Some((&*entities, col_a, col_b))
510 }
511 }
512
513 pub(crate) fn entities_and_required_optional_columns_mut<A, B>(
518 &mut self,
519 ) -> Option<RequiredOptionalColumnsMut<'_, A, B>>
520 where
521 A: Send + Sync + 'static,
522 B: Send + Sync + 'static,
523 {
524 assert_ne!(
525 TypeId::of::<A>(),
526 TypeId::of::<B>(),
527 "cannot borrow the same column mutably twice"
528 );
529 let Self {
530 entities, columns, ..
531 } = self;
532 let ptr = columns as *mut HashMap<TypeId, Box<dyn AnyColumn>>;
533 unsafe {
540 let col_a = (*ptr)
541 .get_mut(&TypeId::of::<A>())?
542 .as_any_mut()
543 .downcast_mut::<Column<A>>()?;
544 let col_b = (*ptr)
545 .get_mut(&TypeId::of::<B>())
546 .and_then(|col| col.as_any_mut().downcast_mut::<Column<B>>());
547 Some((&*entities, col_a, col_b))
548 }
549 }
550
551 pub fn entities_and_three_columns_mut<A, B, C>(
556 &mut self,
557 ) -> Option<ThreeColumnsMut<'_, A, B, C>>
558 where
559 A: Send + Sync + 'static,
560 B: Send + Sync + 'static,
561 C: Send + Sync + 'static,
562 {
563 assert_ne!(
564 TypeId::of::<A>(),
565 TypeId::of::<B>(),
566 "cannot borrow the same column mutably twice"
567 );
568 assert_ne!(
569 TypeId::of::<A>(),
570 TypeId::of::<C>(),
571 "cannot borrow the same column mutably twice"
572 );
573 assert_ne!(
574 TypeId::of::<B>(),
575 TypeId::of::<C>(),
576 "cannot borrow the same column mutably twice"
577 );
578
579 let Self {
580 entities, columns, ..
581 } = self;
582 let ptr = columns as *mut HashMap<TypeId, Box<dyn AnyColumn>>;
583 unsafe {
591 let col_a = (*ptr)
592 .get_mut(&TypeId::of::<A>())?
593 .as_any_mut()
594 .downcast_mut::<Column<A>>()?;
595 let col_b = (*ptr)
596 .get_mut(&TypeId::of::<B>())?
597 .as_any_mut()
598 .downcast_mut::<Column<B>>()?;
599 let col_c = (*ptr)
600 .get_mut(&TypeId::of::<C>())?
601 .as_any_mut()
602 .downcast_mut::<Column<C>>()?;
603 Some((&*entities, col_a, col_b, col_c))
604 }
605 }
606
607 pub(crate) fn stamp_all_ticks(&mut self, row: u32, added: u64, changed: u64) {
609 for col in self.columns.values_mut() {
610 col.stamp_ticks(row as usize, added, changed);
611 }
612 }
613
614 pub(crate) fn stamp_column_ticks(
616 &mut self,
617 type_id: TypeId,
618 row: u32,
619 added: u64,
620 changed: u64,
621 ) {
622 if let Some(col) = self.columns.get_mut(&type_id) {
623 col.stamp_ticks(row as usize, added, changed);
624 }
625 }
626
627 pub fn edge(&self, type_id: TypeId) -> Option<&ArchetypeEdge> {
629 self.edges.get(&type_id)
630 }
631
632 #[allow(dead_code)]
634 pub(crate) fn set_edge(&mut self, type_id: TypeId, edge: ArchetypeEdge) {
635 self.edges.insert(type_id, edge);
636 }
637}
638
639pub struct ArchetypeStore {
645 archetypes: Vec<Archetype>,
646 index: HashMap<ArchetypeLayout, ArchetypeId>,
647 column_factories: HashMap<TypeId, Box<dyn AnyColumn>>,
650}
651
652impl ArchetypeStore {
653 pub fn new() -> Self {
655 Self {
656 archetypes: Vec::new(),
657 index: HashMap::new(),
658 column_factories: HashMap::new(),
659 }
660 }
661
662 pub fn register_column<T: Send + Sync + 'static>(&mut self) {
665 self.column_factories
666 .entry(TypeId::of::<T>())
667 .or_insert_with(|| Box::new(Column::<T>::new()));
668 }
669
670 pub fn get_or_create(&mut self, layout: ArchetypeLayout) -> ArchetypeId {
672 if let Some(&id) = self.index.get(&layout) {
673 return id;
674 }
675 let id = ArchetypeId(self.archetypes.len() as u32);
676 let archetype = Archetype::new(id, layout.clone(), &self.column_factories);
677 self.archetypes.push(archetype);
678 self.index.insert(layout, id);
679 id
680 }
681
682 pub fn get(&self, id: ArchetypeId) -> &Archetype {
684 &self.archetypes[id.0 as usize]
685 }
686
687 pub(crate) fn get_by_index(&self, index: usize) -> Option<&Archetype> {
689 self.archetypes.get(index)
690 }
691
692 pub fn get_mut(&mut self, id: ArchetypeId) -> &mut Archetype {
694 &mut self.archetypes[id.0 as usize]
695 }
696
697 pub(crate) unsafe fn get_by_index_mut_ptr<'w>(
710 this: *mut Self,
711 index: usize,
712 ) -> Option<&'w mut Archetype> {
713 unsafe {
714 let vec_ptr: *mut Vec<Archetype> = std::ptr::addr_of_mut!((*this).archetypes);
715 (&mut *vec_ptr).get_mut(index)
716 }
717 }
718
719 pub fn len(&self) -> usize {
721 self.archetypes.len()
722 }
723
724 pub fn is_empty(&self) -> bool {
726 self.archetypes.is_empty()
727 }
728
729 pub fn iter(&self) -> impl Iterator<Item = &Archetype> {
731 self.archetypes.iter()
732 }
733
734 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Archetype> {
736 self.archetypes.iter_mut()
737 }
738
739 pub fn get_two_mut(
743 &mut self,
744 a: ArchetypeId,
745 b: ArchetypeId,
746 ) -> (&mut Archetype, &mut Archetype) {
747 assert_ne!(a, b, "get_two_mut called with same ArchetypeId");
748 let a_idx = a.0 as usize;
749 let b_idx = b.0 as usize;
750 if a_idx < b_idx {
751 let (left, right) = self.archetypes.split_at_mut(b_idx);
752 (&mut left[a_idx], &mut right[0])
753 } else {
754 let (left, right) = self.archetypes.split_at_mut(a_idx);
755 (&mut right[0], &mut left[b_idx])
756 }
757 }
758}
759
760impl Default for ArchetypeStore {
761 fn default() -> Self {
762 Self::new()
763 }
764}
765
766#[cfg(test)]
771mod tests {
772 use super::*;
773
774 #[test]
777 fn layout_sorts_and_deduplicates() {
778 let a = TypeId::of::<u32>();
779 let b = TypeId::of::<f64>();
780 let l1 = ArchetypeLayout::from_type_ids(&[b, a, b, a]);
781 let l2 = ArchetypeLayout::from_type_ids(&[a, b]);
782 assert_eq!(l1, l2);
783 assert_eq!(l1.len(), 2);
784 }
785
786 #[test]
787 fn layout_contains() {
788 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>(), TypeId::of::<f64>()]);
789 assert!(layout.contains(TypeId::of::<u32>()));
790 assert!(layout.contains(TypeId::of::<f64>()));
791 assert!(!layout.contains(TypeId::of::<bool>()));
792 }
793
794 #[test]
795 fn layout_with_added_and_removed() {
796 let base = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
797 let added = base.with_added(TypeId::of::<f64>());
798 assert_eq!(added.len(), 2);
799 assert!(added.contains(TypeId::of::<f64>()));
800
801 let same = added.with_added(TypeId::of::<u32>());
803 assert_eq!(same, added);
804
805 let removed = added.with_removed(TypeId::of::<u32>());
806 assert_eq!(removed.len(), 1);
807 assert!(!removed.contains(TypeId::of::<u32>()));
808 assert!(removed.contains(TypeId::of::<f64>()));
809
810 let same2 = removed.with_removed(TypeId::of::<bool>());
812 assert_eq!(same2, removed);
813 }
814
815 #[test]
816 fn layout_empty() {
817 let e = ArchetypeLayout::empty();
818 assert!(e.is_empty());
819 assert_eq!(e.len(), 0);
820 }
821
822 #[test]
823 fn layout_hash_eq_regardless_of_input_order() {
824 use std::hash::{DefaultHasher, Hash, Hasher};
825 let a = TypeId::of::<u32>();
826 let b = TypeId::of::<f64>();
827 let c = TypeId::of::<bool>();
828
829 let l1 = ArchetypeLayout::from_type_ids(&[c, a, b]);
830 let l2 = ArchetypeLayout::from_type_ids(&[b, c, a]);
831
832 assert_eq!(l1, l2);
833
834 let hash = |l: &ArchetypeLayout| {
835 let mut h = DefaultHasher::new();
836 l.hash(&mut h);
837 h.finish()
838 };
839 assert_eq!(hash(&l1), hash(&l2));
840 }
841
842 #[test]
845 fn column_push_get() {
846 let mut col = Column::<u32>::new();
847 col.push(10);
848 col.push(20);
849 col.push(30);
850 assert_eq!(col.len(), 3);
851 assert_eq!(*col.get(0).unwrap(), 10);
852 assert_eq!(*col.get(1).unwrap(), 20);
853 assert_eq!(*col.get(2).unwrap(), 30);
854 }
855
856 #[test]
857 fn column_get_mut() {
858 let mut col = Column::<u32>::new();
859 col.push(5);
860 *col.get_mut(0).unwrap() = 99;
861 assert_eq!(*col.get(0).unwrap(), 99);
862 }
863
864 #[test]
865 fn column_swap_remove() {
866 let mut col = Column::<&str>::new();
867 col.push("a");
868 col.push("b");
869 col.push("c");
870 let removed = col.swap_remove(0);
871 assert_eq!(removed, "a");
872 assert_eq!(col.len(), 2);
873 assert_eq!(*col.get(0).unwrap(), "c");
875 assert_eq!(*col.get(1).unwrap(), "b");
876 }
877
878 #[test]
879 fn column_move_to() {
880 let mut src = Column::<u32>::new();
881 src.push(10);
882 src.push(20);
883 src.push(30);
884
885 let mut dst = Column::<u32>::new();
886 src.move_to(1, &mut dst); assert_eq!(src.len(), 2);
889 assert_eq!(dst.len(), 1);
890 assert_eq!(*dst.get(0).unwrap(), 20);
891 assert_eq!(*src.get(0).unwrap(), 10);
892 assert_eq!(*src.get(1).unwrap(), 30);
893 }
894
895 #[test]
896 fn column_new_empty_produces_correct_type() {
897 let col = Column::<f64>::new();
898 let any_col: &dyn AnyColumn = &col;
899 let empty = any_col.new_empty();
900 assert_eq!(empty.len(), 0);
901 assert!(empty.as_any().downcast_ref::<Column<f64>>().is_some());
903 }
904
905 #[test]
908 fn archetype_store_get_or_create_idempotent() {
909 let mut store = ArchetypeStore::new();
910 store.register_column::<u32>();
911 store.register_column::<f64>();
912
913 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>(), TypeId::of::<f64>()]);
914 let id1 = store.get_or_create(layout.clone());
915 let id2 = store.get_or_create(layout);
916 assert_eq!(id1, id2);
917 assert_eq!(store.len(), 1);
918 }
919
920 #[test]
921 fn archetype_push_and_remove_entity() {
922 let mut store = ArchetypeStore::new();
923 store.register_column::<u32>();
924 store.register_column::<String>();
925
926 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>(), TypeId::of::<String>()]);
927 let arch_id = store.get_or_create(layout);
928
929 let e0 = Entity {
930 index: 0,
931 generation: 0,
932 };
933 let e1 = Entity {
934 index: 1,
935 generation: 0,
936 };
937 let e2 = Entity {
938 index: 2,
939 generation: 0,
940 };
941
942 {
944 let arch = store.get_mut(arch_id);
945 arch.column_mut::<u32>().unwrap().push(10);
946 arch.column_mut::<String>()
947 .unwrap()
948 .push("hello".to_string());
949 arch.push_entity(e0);
950
951 arch.column_mut::<u32>().unwrap().push(20);
952 arch.column_mut::<String>()
953 .unwrap()
954 .push("world".to_string());
955 arch.push_entity(e1);
956
957 arch.column_mut::<u32>().unwrap().push(30);
958 arch.column_mut::<String>().unwrap().push("foo".to_string());
959 arch.push_entity(e2);
960
961 assert_eq!(arch.len(), 3);
962 }
963
964 {
966 let arch = store.get_mut(arch_id);
967 let (removed, moved) = arch.swap_remove_entity(0);
968 assert_eq!(removed, e0);
969 assert_eq!(moved, Some(e2)); assert_eq!(arch.len(), 2);
972 assert_eq!(arch.entity_at(0), e2);
973 assert_eq!(arch.entity_at(1), e1);
974
975 assert_eq!(*arch.column::<u32>().unwrap().get(0).unwrap(), 30);
977 assert_eq!(*arch.column::<u32>().unwrap().get(1).unwrap(), 20);
978 }
979 }
980
981 #[test]
982 fn archetype_remove_last_entity_returns_no_moved() {
983 let mut store = ArchetypeStore::new();
984 store.register_column::<u32>();
985
986 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
987 let arch_id = store.get_or_create(layout);
988
989 let e0 = Entity {
990 index: 0,
991 generation: 0,
992 };
993
994 let arch = store.get_mut(arch_id);
995 arch.column_mut::<u32>().unwrap().push(42);
996 arch.push_entity(e0);
997
998 let (removed, moved) = arch.swap_remove_entity(0);
999 assert_eq!(removed, e0);
1000 assert!(moved.is_none());
1001 assert!(arch.is_empty());
1002 }
1003
1004 #[test]
1005 fn archetype_column_len_matches_entity_count() {
1006 let mut store = ArchetypeStore::new();
1007 store.register_column::<u32>();
1008 store.register_column::<bool>();
1009
1010 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>(), TypeId::of::<bool>()]);
1011 let arch_id = store.get_or_create(layout);
1012
1013 let arch = store.get_mut(arch_id);
1014 for i in 0..5 {
1015 arch.column_mut::<u32>().unwrap().push(i);
1016 arch.column_mut::<bool>().unwrap().push(i % 2 == 0);
1017 arch.push_entity(Entity {
1018 index: i,
1019 generation: 0,
1020 });
1021 }
1022
1023 assert_eq!(arch.len(), 5);
1024 assert_eq!(arch.column::<u32>().unwrap().len(), 5);
1025 assert_eq!(arch.column::<bool>().unwrap().len(), 5);
1026 }
1027
1028 #[test]
1029 fn archetype_store_multiple_layouts() {
1030 let mut store = ArchetypeStore::new();
1031 store.register_column::<u32>();
1032 store.register_column::<f64>();
1033 store.register_column::<bool>();
1034
1035 let l1 = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
1036 let l2 = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>(), TypeId::of::<f64>()]);
1037 let l3 = ArchetypeLayout::from_type_ids(&[
1038 TypeId::of::<u32>(),
1039 TypeId::of::<f64>(),
1040 TypeId::of::<bool>(),
1041 ]);
1042
1043 let id1 = store.get_or_create(l1);
1044 let id2 = store.get_or_create(l2);
1045 let id3 = store.get_or_create(l3);
1046
1047 assert_ne!(id1, id2);
1048 assert_ne!(id2, id3);
1049 assert_eq!(store.len(), 3);
1050 }
1051
1052 #[test]
1055 fn edge_cache_starts_empty() {
1056 let mut store = ArchetypeStore::new();
1057 store.register_column::<u32>();
1058
1059 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
1060 let arch_id = store.get_or_create(layout);
1061 let arch = store.get(arch_id);
1062
1063 assert!(arch.edge(TypeId::of::<f64>()).is_none());
1064 }
1065
1066 #[test]
1067 fn edge_cache_set_and_get() {
1068 let mut store = ArchetypeStore::new();
1069 store.register_column::<u32>();
1070 store.register_column::<f64>();
1071
1072 let l1 = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
1073 let l2 = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>(), TypeId::of::<f64>()]);
1074 let id1 = store.get_or_create(l1);
1075 let id2 = store.get_or_create(l2);
1076
1077 store.get_mut(id1).set_edge(
1079 TypeId::of::<f64>(),
1080 ArchetypeEdge {
1081 add: Some(id2),
1082 remove: None,
1083 },
1084 );
1085
1086 let edge = store.get(id1).edge(TypeId::of::<f64>()).unwrap();
1087 assert_eq!(edge.add, Some(id2));
1088 assert_eq!(edge.remove, None);
1089 }
1090
1091 #[test]
1094 fn column_iter() {
1095 let mut col = Column::<u32>::new();
1096 col.push(10);
1097 col.push(20);
1098 col.push(30);
1099 let vals: Vec<&u32> = col.iter().collect();
1100 assert_eq!(vals, vec![&10, &20, &30]);
1101 }
1102
1103 #[test]
1104 fn column_iter_mut() {
1105 let mut col = Column::<u32>::new();
1106 col.push(1);
1107 col.push(2);
1108 for val in col.iter_mut() {
1109 *val *= 10;
1110 }
1111 assert_eq!(*col.get(0).unwrap(), 10);
1112 assert_eq!(*col.get(1).unwrap(), 20);
1113 }
1114
1115 #[test]
1116 fn column_as_mut_ptr_points_to_first_element() {
1117 let mut col = Column::<u32>::new();
1118 col.push(7);
1119 col.push(9);
1120
1121 let ptr = col.as_mut_ptr();
1122
1123 unsafe {
1125 assert_eq!(*ptr, 7);
1126 assert_eq!(*ptr.add(1), 9);
1127 }
1128 }
1129
1130 #[test]
1133 fn archetype_store_get_two_mut() {
1134 let mut store = ArchetypeStore::new();
1135 store.register_column::<u32>();
1136 store.register_column::<f64>();
1137
1138 let l1 = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
1139 let l2 = ArchetypeLayout::from_type_ids(&[TypeId::of::<f64>()]);
1140 let id1 = store.get_or_create(l1);
1141 let id2 = store.get_or_create(l2);
1142
1143 let (a1, a2) = store.get_two_mut(id1, id2);
1144 assert_eq!(a1.id(), id1);
1145 assert_eq!(a2.id(), id2);
1146 }
1147
1148 #[test]
1149 #[should_panic(expected = "get_two_mut called with same ArchetypeId")]
1150 fn archetype_store_get_two_mut_same_panics() {
1151 let mut store = ArchetypeStore::new();
1152 store.register_column::<u32>();
1153 let l = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
1154 let id = store.get_or_create(l);
1155 store.get_two_mut(id, id);
1156 }
1157
1158 #[test]
1161 fn archetype_swap_remove_entity_entry() {
1162 let mut store = ArchetypeStore::new();
1163 store.register_column::<u32>();
1164 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
1165 let arch_id = store.get_or_create(layout);
1166 let arch = store.get_mut(arch_id);
1167
1168 let e0 = Entity {
1169 index: 0,
1170 generation: 0,
1171 };
1172 let e1 = Entity {
1173 index: 1,
1174 generation: 0,
1175 };
1176
1177 arch.column_mut::<u32>().unwrap().push(10);
1178 arch.push_entity(e0);
1179 arch.column_mut::<u32>().unwrap().push(20);
1180 arch.push_entity(e1);
1181
1182 arch.column_mut::<u32>().unwrap().swap_remove(0);
1184 let (removed, moved) = arch.swap_remove_entity_entry(0);
1186 assert_eq!(removed, e0);
1187 assert_eq!(moved, Some(e1));
1188 assert_eq!(arch.len(), 1);
1189 }
1190
1191 #[test]
1192 fn archetype_entities_and_column_mut() {
1193 let mut store = ArchetypeStore::new();
1194 store.register_column::<u32>();
1195 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>()]);
1196 let arch_id = store.get_or_create(layout);
1197 let arch = store.get_mut(arch_id);
1198
1199 let e0 = Entity {
1200 index: 0,
1201 generation: 0,
1202 };
1203 arch.column_mut::<u32>().unwrap().push(42);
1204 arch.push_entity(e0);
1205
1206 {
1207 let (entities, col) = arch.entities_and_column_mut::<u32>().unwrap();
1208 assert_eq!(entities.len(), 1);
1209 assert_eq!(entities[0], e0);
1210 *col.get_mut(0).unwrap() = 99;
1211 } assert_eq!(*arch.column::<u32>().unwrap().get(0).unwrap(), 99);
1213 }
1214
1215 #[test]
1216 fn archetype_entities_and_two_columns_mut() {
1217 let mut store = ArchetypeStore::new();
1218 store.register_column::<u32>();
1219 store.register_column::<f64>();
1220 let layout = ArchetypeLayout::from_type_ids(&[TypeId::of::<u32>(), TypeId::of::<f64>()]);
1221 let arch_id = store.get_or_create(layout);
1222 let arch = store.get_mut(arch_id);
1223
1224 let e0 = Entity {
1225 index: 0,
1226 generation: 0,
1227 };
1228 arch.column_mut::<u32>().unwrap().push(10);
1229 arch.column_mut::<f64>().unwrap().push(1.5);
1230 arch.push_entity(e0);
1231
1232 {
1233 let (entities, col_u, col_f) = arch.entities_and_two_columns_mut::<u32, f64>().unwrap();
1234 assert_eq!(entities[0], e0);
1235 *col_u.get_mut(0).unwrap() = 20;
1236 *col_f.get_mut(0).unwrap() = 2.5;
1237 } assert_eq!(*arch.column::<u32>().unwrap().get(0).unwrap(), 20);
1239 assert_eq!(*arch.column::<f64>().unwrap().get(0).unwrap(), 2.5);
1240 }
1241
1242 #[test]
1243 fn archetype_entities_and_three_columns_mut() {
1244 let mut store = ArchetypeStore::new();
1245 store.register_column::<u32>();
1246 store.register_column::<f64>();
1247 store.register_column::<bool>();
1248 let layout = ArchetypeLayout::from_type_ids(&[
1249 TypeId::of::<u32>(),
1250 TypeId::of::<f64>(),
1251 TypeId::of::<bool>(),
1252 ]);
1253 let arch_id = store.get_or_create(layout);
1254 let arch = store.get_mut(arch_id);
1255
1256 let e0 = Entity {
1257 index: 0,
1258 generation: 0,
1259 };
1260 arch.column_mut::<u32>().unwrap().push(10);
1261 arch.column_mut::<f64>().unwrap().push(1.5);
1262 arch.column_mut::<bool>().unwrap().push(true);
1263 arch.push_entity(e0);
1264
1265 {
1266 let (entities, col_u, col_f, col_b) = arch
1267 .entities_and_three_columns_mut::<u32, f64, bool>()
1268 .unwrap();
1269 assert_eq!(entities[0], e0);
1270 *col_u.get_mut(0).unwrap() = 20;
1271 *col_f.get_mut(0).unwrap() = 2.5;
1272 *col_b.get_mut(0).unwrap() = false;
1273 }
1274
1275 assert_eq!(*arch.column::<u32>().unwrap().get(0).unwrap(), 20);
1276 assert_eq!(*arch.column::<f64>().unwrap().get(0).unwrap(), 2.5);
1277 assert!(!arch.column::<bool>().unwrap().get(0).unwrap());
1278 }
1279
1280 #[test]
1283 fn column_push_defaults_to_sentinel_ticks() {
1284 let mut col = Column::<u32>::new();
1285 col.push(10);
1286 col.push(20);
1287 assert_eq!(col.added_tick(0), 0);
1288 assert_eq!(col.changed_tick(0), 0);
1289 assert_eq!(col.added_tick(1), 0);
1290 assert_eq!(col.changed_tick(1), 0);
1291 }
1292
1293 #[test]
1294 fn column_push_with_ticks() {
1295 let mut col = Column::<u32>::new();
1296 col.push_with_ticks(10, 5, 7);
1297 col.push_with_ticks(20, 8, 9);
1298 assert_eq!(col.added_tick(0), 5);
1299 assert_eq!(col.changed_tick(0), 7);
1300 assert_eq!(col.added_tick(1), 8);
1301 assert_eq!(col.changed_tick(1), 9);
1302 }
1303
1304 #[test]
1305 fn column_set_ticks() {
1306 let mut col = Column::<u32>::new();
1307 col.push(10);
1308 col.set_added_tick(0, 3);
1309 col.set_changed_tick(0, 5);
1310 assert_eq!(col.added_tick(0), 3);
1311 assert_eq!(col.changed_tick(0), 5);
1312 }
1313
1314 #[test]
1315 fn column_swap_remove_keeps_ticks_in_sync() {
1316 let mut col = Column::<u32>::new();
1317 col.push_with_ticks(10, 1, 2);
1318 col.push_with_ticks(20, 3, 4);
1319 col.push_with_ticks(30, 5, 6);
1320
1321 let removed = col.swap_remove(0);
1323 assert_eq!(removed, 10);
1324 assert_eq!(col.len(), 2);
1325 assert_eq!(*col.get(0).unwrap(), 30);
1327 assert_eq!(col.added_tick(0), 5);
1328 assert_eq!(col.changed_tick(0), 6);
1329 assert_eq!(*col.get(1).unwrap(), 20);
1331 assert_eq!(col.added_tick(1), 3);
1332 assert_eq!(col.changed_tick(1), 4);
1333 }
1334
1335 #[test]
1336 fn column_move_to_transfers_ticks() {
1337 let mut src = Column::<u32>::new();
1338 src.push_with_ticks(10, 1, 2);
1339 src.push_with_ticks(20, 3, 4);
1340
1341 let mut dst = Column::<u32>::new();
1342
1343 AnyColumn::move_to(&mut src, 0, &mut dst);
1345
1346 assert_eq!(src.len(), 1);
1348 assert_eq!(*src.get(0).unwrap(), 20);
1349 assert_eq!(src.added_tick(0), 3);
1350 assert_eq!(src.changed_tick(0), 4);
1351
1352 assert_eq!(dst.len(), 1);
1354 assert_eq!(*dst.get(0).unwrap(), 10);
1355 assert_eq!(dst.added_tick(0), 1);
1356 assert_eq!(dst.changed_tick(0), 2);
1357 }
1358
1359 #[test]
1360 fn column_swap_remove_and_drop_keeps_ticks_in_sync() {
1361 let mut col = Column::<u32>::new();
1362 col.push_with_ticks(10, 1, 2);
1363 col.push_with_ticks(20, 3, 4);
1364
1365 AnyColumn::swap_remove_and_drop(&mut col, 0);
1366 assert_eq!(col.len(), 1);
1367 assert_eq!(*col.get(0).unwrap(), 20);
1368 assert_eq!(col.added_tick(0), 3);
1369 assert_eq!(col.changed_tick(0), 4);
1370 }
1371
1372 #[test]
1373 fn column_tick_slices() {
1374 let mut col = Column::<u32>::new();
1375 col.push_with_ticks(10, 1, 2);
1376 col.push_with_ticks(20, 3, 4);
1377 assert_eq!(col.added_ticks(), &[1, 3]);
1378 assert_eq!(col.changed_ticks(), &[2, 4]);
1379 }
1380}