anput/
archetype.rs

1use crate::{
2    bundle::{Bundle, BundleColumns},
3    component::Component,
4    entity::{Entity, EntityDenseMap},
5};
6use intuicio_core::types::Type;
7use intuicio_data::{Finalize, non_zero_alloc, non_zero_dealloc, type_hash::TypeHash};
8use std::{
9    alloc::Layout,
10    error::Error,
11    marker::PhantomData,
12    sync::{
13        Arc,
14        atomic::{AtomicBool, AtomicUsize, Ordering},
15    },
16};
17
18fn traced_spin_loop() {
19    #[cfg(feature = "deadlock-trace")]
20    println!(
21        "* DEADLOCK BACKTRACE: {}",
22        std::backtrace::Backtrace::force_capture()
23    );
24    std::hint::spin_loop();
25}
26
27#[derive(Debug, PartialEq, Eq)]
28pub enum ArchetypeError {
29    ColumnAlreadyUniquelyAccessed {
30        type_hash: TypeHash,
31    },
32    ColumnNotFound {
33        type_hash: TypeHash,
34    },
35    ColumnTypeIsDuplicated {
36        type_hash: TypeHash,
37        index: usize,
38        duplicate_index: usize,
39    },
40    ColumnTypeMismatch {
41        provided: TypeHash,
42        expected: TypeHash,
43    },
44    IndexNotFound {
45        index: usize,
46    },
47    IndexAlreadyOccupied {
48        index: usize,
49    },
50    EntityNotFound {
51        entity: Entity,
52    },
53    EntityAlreadyOccupied {
54        entity: Entity,
55    },
56    ColumnSdirLocked {
57        type_hash: TypeHash,
58    },
59}
60
61impl Error for ArchetypeError {}
62
63impl std::fmt::Display for ArchetypeError {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        match self {
66            Self::ColumnAlreadyUniquelyAccessed { type_hash } => {
67                write!(f, "Column is already uniquelly accessed: {type_hash:?}")
68            }
69            Self::ColumnNotFound { type_hash } => write!(f, "Column not found: {type_hash:?}"),
70            Self::ColumnTypeIsDuplicated {
71                type_hash,
72                index,
73                duplicate_index,
74            } => write!(
75                f,
76                "Column type: {type_hash:?} at index: {index} has duplicate at index: {duplicate_index}"
77            ),
78            Self::ColumnTypeMismatch { provided, expected } => write!(
79                f,
80                "Provided column: {provided:?} does not match expected: {expected:?}"
81            ),
82            Self::IndexNotFound { index } => write!(f, "Entity index not found: {index}"),
83            Self::IndexAlreadyOccupied { index } => {
84                write!(f, "Entity index already occupied: {index}")
85            }
86            Self::EntityNotFound { entity } => write!(f, "Entity not found: {entity}"),
87            Self::EntityAlreadyOccupied { entity } => {
88                write!(f, "Entity already occupied: {entity}")
89            }
90            Self::ColumnSdirLocked { type_hash } => write!(
91                f,
92                "Column: {type_hash:?} is locked for Spawn/Despawn/Insert/Remove operations"
93            ),
94        }
95    }
96}
97
98#[derive(Debug, Clone, Copy, Eq)]
99pub struct ArchetypeColumnInfo {
100    type_hash: TypeHash,
101    layout: Layout,
102    finalizer: unsafe fn(*mut ()),
103}
104
105impl ArchetypeColumnInfo {
106    pub fn new<T: Finalize>() -> Self {
107        Self {
108            type_hash: TypeHash::of::<T>(),
109            layout: Layout::new::<T>().pad_to_align(),
110            finalizer: T::finalize_raw,
111        }
112    }
113
114    /// # Safety
115    pub unsafe fn new_raw(
116        type_hash: TypeHash,
117        layout: Layout,
118        finalizer: unsafe fn(*mut ()),
119    ) -> Self {
120        Self {
121            type_hash,
122            layout: layout.pad_to_align(),
123            finalizer,
124        }
125    }
126
127    pub fn from_type(type_: &Type) -> Self {
128        Self {
129            type_hash: type_.type_hash(),
130            layout: *type_.layout(),
131            finalizer: unsafe { type_.finalizer() },
132        }
133    }
134
135    #[inline]
136    pub fn type_hash(&self) -> TypeHash {
137        self.type_hash
138    }
139
140    #[inline]
141    pub fn layout(&self) -> Layout {
142        self.layout
143    }
144
145    #[inline]
146    pub fn finalizer(&self) -> unsafe fn(*mut ()) {
147        self.finalizer
148    }
149}
150
151impl PartialEq for ArchetypeColumnInfo {
152    fn eq(&self, other: &Self) -> bool {
153        self.type_hash.eq(&other.type_hash) && self.layout.eq(&other.layout)
154    }
155}
156
157pub struct ArchetypeColumnAccess<'a, const LOCKING: bool, T: Component> {
158    column: &'a Column,
159    size: usize,
160    unique: bool,
161    _phantom: PhantomData<fn() -> T>,
162}
163
164impl<const LOCKING: bool, T: Component> Drop for ArchetypeColumnAccess<'_, LOCKING, T> {
165    fn drop(&mut self) {
166        if self.unique {
167            if LOCKING {
168                while self
169                    .column
170                    .unique_access
171                    .compare_exchange_weak(true, false, Ordering::Acquire, Ordering::Relaxed)
172                    .is_err()
173                {
174                    traced_spin_loop();
175                }
176            } else {
177                let _ = self.column.unique_access.compare_exchange(
178                    true,
179                    false,
180                    Ordering::Acquire,
181                    Ordering::Relaxed,
182                );
183            }
184        }
185    }
186}
187
188impl<'a, const LOCKING: bool, T: Component> ArchetypeColumnAccess<'a, LOCKING, T> {
189    unsafe fn new(column: &'a Column, unique: bool, size: usize) -> Result<Self, ArchetypeError> {
190        if unique {
191            if LOCKING {
192                while column
193                    .unique_access
194                    .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
195                    .is_err()
196                {
197                    traced_spin_loop();
198                }
199            } else if column
200                .unique_access
201                .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
202                .is_err()
203            {
204                return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
205                    type_hash: column.info.type_hash,
206                });
207            }
208        } else if LOCKING {
209            while column.unique_access.load(Ordering::Acquire) {
210                traced_spin_loop();
211            }
212        } else if column.unique_access.load(Ordering::Acquire) {
213            return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
214                type_hash: column.info.type_hash,
215            });
216        }
217        Ok(Self {
218            column,
219            size,
220            unique,
221            _phantom: PhantomData,
222        })
223    }
224
225    #[inline]
226    pub fn info(&self) -> &ArchetypeColumnInfo {
227        &self.column.info
228    }
229
230    #[inline]
231    pub fn size(&self) -> usize {
232        self.size
233    }
234
235    #[inline]
236    pub fn is_unique(&self) -> bool {
237        self.unique
238    }
239
240    /// # Safety
241    #[inline]
242    pub unsafe fn memory(&self) -> *mut u8 {
243        self.column.memory
244    }
245
246    /// # Safety
247    pub unsafe fn data(&self, index: usize) -> Result<*mut u8, ArchetypeError> {
248        if index < self.size {
249            Ok(unsafe {
250                self.column
251                    .memory
252                    .add(index * self.column.info.layout.size())
253            })
254        } else {
255            Err(ArchetypeError::IndexNotFound { index })
256        }
257    }
258
259    pub fn read(&self, index: usize) -> Option<&T> {
260        if index < self.size {
261            unsafe {
262                self.column
263                    .memory
264                    .add(index * self.column.info.layout.size())
265                    .cast::<T>()
266                    .as_ref()
267            }
268        } else {
269            None
270        }
271    }
272
273    pub fn write(&mut self, index: usize) -> Option<&mut T> {
274        if index < self.size && self.unique {
275            unsafe {
276                self.column
277                    .memory
278                    .add(index * self.column.info.layout.size())
279                    .cast::<T>()
280                    .as_mut()
281            }
282        } else {
283            None
284        }
285    }
286}
287
288pub struct ArchetypeDynamicColumnAccess<'a, const LOCKING: bool> {
289    column: &'a Column,
290    size: usize,
291    unique: bool,
292}
293
294impl<const LOCKING: bool> Drop for ArchetypeDynamicColumnAccess<'_, LOCKING> {
295    fn drop(&mut self) {
296        if self.unique {
297            if LOCKING {
298                while self
299                    .column
300                    .unique_access
301                    .compare_exchange_weak(true, false, Ordering::Acquire, Ordering::Relaxed)
302                    .is_err()
303                {
304                    traced_spin_loop();
305                }
306            } else {
307                let _ = self.column.unique_access.compare_exchange(
308                    true,
309                    false,
310                    Ordering::Acquire,
311                    Ordering::Relaxed,
312                );
313            }
314        }
315    }
316}
317
318impl<'a, const LOCKING: bool> ArchetypeDynamicColumnAccess<'a, LOCKING> {
319    fn new(column: &'a Column, unique: bool, size: usize) -> Result<Self, ArchetypeError> {
320        if unique {
321            if LOCKING {
322                while column
323                    .unique_access
324                    .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
325                    .is_err()
326                {
327                    traced_spin_loop();
328                }
329            } else if column
330                .unique_access
331                .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
332                .is_err()
333            {
334                return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
335                    type_hash: column.info.type_hash,
336                });
337            }
338        } else if LOCKING {
339            while column.unique_access.load(Ordering::Acquire) {
340                traced_spin_loop();
341            }
342        } else if column.unique_access.load(Ordering::Acquire) {
343            return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
344                type_hash: column.info.type_hash,
345            });
346        }
347        Ok(Self {
348            column,
349            size,
350            unique,
351        })
352    }
353
354    #[inline]
355    pub fn info(&self) -> &ArchetypeColumnInfo {
356        &self.column.info
357    }
358
359    #[inline]
360    pub fn size(&self) -> usize {
361        self.size
362    }
363
364    #[inline]
365    pub fn is_unique(&self) -> bool {
366        self.unique
367    }
368
369    /// # Safety
370    #[inline]
371    pub unsafe fn memory(&self) -> *mut u8 {
372        self.column.memory
373    }
374
375    /// # Safety
376    pub unsafe fn data(&self, index: usize) -> Result<*mut u8, ArchetypeError> {
377        if index < self.size {
378            Ok(unsafe {
379                self.column
380                    .memory
381                    .add(index * self.column.info.layout.size())
382            })
383        } else {
384            Err(ArchetypeError::IndexNotFound { index })
385        }
386    }
387
388    pub fn read<T: Component>(&self, index: usize) -> Option<&T> {
389        if index < self.size && self.column.info.type_hash == TypeHash::of::<T>() {
390            unsafe {
391                self.column
392                    .memory
393                    .add(index * self.column.info.layout.size())
394                    .cast::<T>()
395                    .as_ref()
396            }
397        } else {
398            None
399        }
400    }
401
402    pub fn write<T: Component>(&mut self, index: usize) -> Option<&mut T> {
403        if index < self.size && self.unique && self.column.info.type_hash == TypeHash::of::<T>() {
404            unsafe {
405                self.column
406                    .memory
407                    .add(index * self.column.info.layout.size())
408                    .cast::<T>()
409                    .as_mut()
410            }
411        } else {
412            None
413        }
414    }
415
416    pub fn dynamic_item(
417        &'_ self,
418        index: usize,
419    ) -> Result<ArchetypeDynamicColumnItem<'_>, ArchetypeError> {
420        let memory = unsafe { self.data(index)? };
421        Ok(ArchetypeDynamicColumnItem {
422            memory,
423            type_hash: self.column.info.type_hash,
424            unique: self.unique,
425            _phantom: PhantomData,
426        })
427    }
428}
429
430pub struct ArchetypeEntityColumnAccess<'a, const LOCKING: bool, T: Component> {
431    column: &'a Column,
432    index: usize,
433    unique: bool,
434    _phantom: PhantomData<fn() -> T>,
435}
436
437impl<const LOCKING: bool, T: Component> Drop for ArchetypeEntityColumnAccess<'_, LOCKING, T> {
438    fn drop(&mut self) {
439        if self.unique {
440            if LOCKING {
441                while self
442                    .column
443                    .unique_access
444                    .compare_exchange_weak(true, false, Ordering::Acquire, Ordering::Relaxed)
445                    .is_err()
446                {
447                    traced_spin_loop();
448                }
449            } else {
450                let _ = self.column.unique_access.compare_exchange(
451                    true,
452                    false,
453                    Ordering::Acquire,
454                    Ordering::Relaxed,
455                );
456            }
457        }
458    }
459}
460
461impl<'a, const LOCKING: bool, T: Component> ArchetypeEntityColumnAccess<'a, LOCKING, T> {
462    unsafe fn new(column: &'a Column, unique: bool, index: usize) -> Result<Self, ArchetypeError> {
463        if unique {
464            if LOCKING {
465                while column
466                    .unique_access
467                    .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
468                    .is_err()
469                {
470                    traced_spin_loop();
471                }
472            } else if column
473                .unique_access
474                .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
475                .is_err()
476            {
477                return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
478                    type_hash: column.info.type_hash,
479                });
480            }
481        } else if LOCKING {
482            while column.unique_access.load(Ordering::Acquire) {
483                traced_spin_loop();
484            }
485        } else if column.unique_access.load(Ordering::Acquire) {
486            return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
487                type_hash: column.info.type_hash,
488            });
489        }
490        Ok(Self {
491            column,
492            index,
493            unique,
494            _phantom: PhantomData,
495        })
496    }
497
498    #[inline]
499    pub fn info(&self) -> &ArchetypeColumnInfo {
500        &self.column.info
501    }
502
503    #[inline]
504    pub fn is_unique(&self) -> bool {
505        self.unique
506    }
507
508    /// # Safety
509    #[inline]
510    pub unsafe fn data(&self) -> *mut u8 {
511        unsafe {
512            self.column
513                .memory
514                .add(self.index * self.column.info.layout.size())
515        }
516    }
517
518    pub fn read(&self) -> Option<&T> {
519        unsafe {
520            self.column
521                .memory
522                .add(self.index * self.column.info.layout.size())
523                .cast::<T>()
524                .as_ref()
525        }
526    }
527
528    pub fn write(&mut self) -> Option<&mut T> {
529        if self.unique {
530            unsafe {
531                self.column
532                    .memory
533                    .add(self.index * self.column.info.layout.size())
534                    .cast::<T>()
535                    .as_mut()
536            }
537        } else {
538            None
539        }
540    }
541}
542
543pub struct ArchetypeDynamicEntityColumnAccess<'a, const LOCKING: bool> {
544    column: &'a Column,
545    index: usize,
546    unique: bool,
547}
548
549impl<const LOCKING: bool> Drop for ArchetypeDynamicEntityColumnAccess<'_, LOCKING> {
550    fn drop(&mut self) {
551        if self.unique {
552            if LOCKING {
553                while self
554                    .column
555                    .unique_access
556                    .compare_exchange_weak(true, false, Ordering::Acquire, Ordering::Relaxed)
557                    .is_err()
558                {
559                    traced_spin_loop();
560                }
561            } else {
562                let _ = self.column.unique_access.compare_exchange(
563                    true,
564                    false,
565                    Ordering::Acquire,
566                    Ordering::Relaxed,
567                );
568            }
569        }
570    }
571}
572
573impl<'a, const LOCKING: bool> ArchetypeDynamicEntityColumnAccess<'a, LOCKING> {
574    fn new(column: &'a Column, unique: bool, index: usize) -> Result<Self, ArchetypeError> {
575        if unique {
576            if LOCKING {
577                while column
578                    .unique_access
579                    .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
580                    .is_err()
581                {
582                    traced_spin_loop();
583                }
584            } else if column
585                .unique_access
586                .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
587                .is_err()
588            {
589                return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
590                    type_hash: column.info.type_hash,
591                });
592            }
593        } else if LOCKING {
594            while column.unique_access.load(Ordering::Acquire) {
595                traced_spin_loop();
596            }
597        } else if column.unique_access.load(Ordering::Acquire) {
598            return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
599                type_hash: column.info.type_hash,
600            });
601        }
602        Ok(Self {
603            column,
604            index,
605            unique,
606        })
607    }
608
609    #[inline]
610    pub fn info(&self) -> &ArchetypeColumnInfo {
611        &self.column.info
612    }
613
614    #[inline]
615    pub fn is_unique(&self) -> bool {
616        self.unique
617    }
618
619    /// # Safety
620    #[inline]
621    pub unsafe fn data(&self) -> *mut u8 {
622        unsafe {
623            self.column
624                .memory
625                .add(self.index * self.column.info.layout.size())
626        }
627    }
628
629    pub fn read<T: Component>(&self) -> Option<&T> {
630        if self.column.info.type_hash == TypeHash::of::<T>() {
631            unsafe {
632                self.column
633                    .memory
634                    .add(self.index * self.column.info.layout.size())
635                    .cast::<T>()
636                    .as_ref()
637            }
638        } else {
639            None
640        }
641    }
642
643    pub fn write<T: Component>(&mut self) -> Option<&mut T> {
644        if self.unique && self.column.info.type_hash == TypeHash::of::<T>() {
645            unsafe {
646                self.column
647                    .memory
648                    .add(self.index * self.column.info.layout.size())
649                    .cast::<T>()
650                    .as_mut()
651            }
652        } else {
653            None
654        }
655    }
656}
657
658pub struct ArchetypeEntityRowAccess<'a> {
659    columns: Box<[&'a Column]>,
660    index: usize,
661}
662
663impl Drop for ArchetypeEntityRowAccess<'_> {
664    fn drop(&mut self) {
665        for column in self.columns.as_ref() {
666            while column
667                .unique_access
668                .compare_exchange_weak(true, false, Ordering::Acquire, Ordering::Relaxed)
669                .is_err()
670            {
671                traced_spin_loop();
672            }
673        }
674    }
675}
676
677impl<'a> ArchetypeEntityRowAccess<'a> {
678    fn new(columns: Box<[&'a Column]>, index: usize) -> Self {
679        for column in columns.as_ref() {
680            while column
681                .unique_access
682                .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
683                .is_err()
684            {
685                traced_spin_loop();
686            }
687        }
688        Self { columns, index }
689    }
690
691    pub fn len(&self) -> usize {
692        self.columns.as_ref().len()
693    }
694
695    pub fn is_empty(&self) -> bool {
696        self.columns.as_ref().is_empty()
697    }
698
699    /// # Safety
700    pub unsafe fn data(&self, type_hash: TypeHash) -> Result<*mut u8, ArchetypeError> {
701        for column in self.columns.as_ref() {
702            if column.info.type_hash == type_hash {
703                return Ok(unsafe { column.memory.add(self.index * column.info.layout.size()) });
704            }
705        }
706        Err(ArchetypeError::ColumnNotFound { type_hash })
707    }
708
709    pub fn types(&self) -> impl Iterator<Item = TypeHash> + '_ {
710        self.columns.iter().map(|column| column.info.type_hash)
711    }
712
713    pub fn columns(&self) -> impl Iterator<Item = &ArchetypeColumnInfo> {
714        self.columns.iter().map(|column| &column.info)
715    }
716
717    pub fn read<T: Component>(&self) -> Option<&T> {
718        let type_hash = TypeHash::of::<T>();
719        for column in self.columns.as_ref() {
720            if column.info.type_hash == type_hash {
721                unsafe {
722                    return column
723                        .memory
724                        .add(self.index * column.info.layout.size())
725                        .cast::<T>()
726                        .as_ref();
727                }
728            }
729        }
730        None
731    }
732
733    pub fn write<T: Component>(&mut self) -> Option<&mut T> {
734        let type_hash = TypeHash::of::<T>();
735        for column in self.columns.as_ref() {
736            if column.info.type_hash == type_hash {
737                unsafe {
738                    return column
739                        .memory
740                        .add(self.index * column.info.layout.size())
741                        .cast::<T>()
742                        .as_mut();
743                }
744            }
745        }
746        None
747    }
748
749    /// # Safety
750    pub unsafe fn initialize<T: Component>(&self, value: T) -> Result<(), ArchetypeError> {
751        let type_hash = TypeHash::of::<T>();
752        for column in self.columns.as_ref() {
753            if column.info.type_hash == type_hash {
754                unsafe {
755                    column
756                        .memory
757                        .add(self.index * column.info.layout.size())
758                        .cast::<T>()
759                        .write(value)
760                };
761                return Ok(());
762            }
763        }
764        Err(ArchetypeError::ColumnNotFound { type_hash })
765    }
766
767    /// # Safety
768    pub unsafe fn initialize_raw(&self, type_: &Type) -> Result<(), ArchetypeError> {
769        let type_hash = type_.type_hash();
770        for column in self.columns.as_ref() {
771            if column.info.type_hash == type_hash {
772                unsafe {
773                    type_.initialize(column.memory.add(self.index * column.info.layout.size()) as _)
774                };
775                return Ok(());
776            }
777        }
778        Err(ArchetypeError::ColumnNotFound { type_hash })
779    }
780}
781
782pub struct ArchetypeColumnReadIter<'a, T: Component> {
783    memory: *mut u8,
784    stride: usize,
785    left: usize,
786    _phantom: PhantomData<fn() -> &'a T>,
787}
788
789impl<'a, T: Component> ArchetypeColumnReadIter<'a, T> {
790    fn new<const LOCKING: bool>(column: &'a Column, size: usize) -> Result<Self, ArchetypeError> {
791        if LOCKING {
792            while column.unique_access.load(Ordering::Acquire) {
793                traced_spin_loop();
794            }
795        } else if column.unique_access.load(Ordering::Acquire) {
796            return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
797                type_hash: column.info.type_hash,
798            });
799        }
800        Ok(Self {
801            memory: column.memory,
802            stride: column.info.layout.size(),
803            left: size,
804            _phantom: PhantomData,
805        })
806    }
807}
808
809impl<'a, T: Component> Iterator for ArchetypeColumnReadIter<'a, T> {
810    type Item = &'a T;
811
812    fn next(&mut self) -> Option<Self::Item> {
813        if self.left == 0 {
814            return None;
815        }
816        self.left -= 1;
817        unsafe {
818            let result = self.memory.cast::<T>().as_ref()?;
819            self.memory = self.memory.add(self.stride);
820            Some(result)
821        }
822    }
823
824    fn size_hint(&self) -> (usize, Option<usize>) {
825        (self.left, Some(self.left))
826    }
827}
828
829pub struct ArchetypeColumnWriteIter<'a, const LOCKING: bool, T: Component> {
830    column: &'a Column,
831    memory: *mut u8,
832    stride: usize,
833    left: usize,
834    _phantom: PhantomData<fn() -> &'a mut T>,
835}
836
837impl<const LOCKING: bool, T: Component> Drop for ArchetypeColumnWriteIter<'_, LOCKING, T> {
838    fn drop(&mut self) {
839        if LOCKING {
840            while self
841                .column
842                .unique_access
843                .compare_exchange_weak(true, false, Ordering::Acquire, Ordering::Relaxed)
844                .is_err()
845            {
846                traced_spin_loop();
847            }
848        } else {
849            let _ = self.column.unique_access.compare_exchange(
850                true,
851                false,
852                Ordering::Acquire,
853                Ordering::Relaxed,
854            );
855        }
856    }
857}
858
859impl<'a, const LOCKING: bool, T: Component> ArchetypeColumnWriteIter<'a, LOCKING, T> {
860    fn new(column: &'a Column, size: usize) -> Result<Self, ArchetypeError> {
861        if LOCKING {
862            while column
863                .unique_access
864                .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
865                .is_err()
866            {
867                traced_spin_loop();
868            }
869        } else if column
870            .unique_access
871            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
872            .is_err()
873        {
874            return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
875                type_hash: column.info.type_hash,
876            });
877        }
878        Ok(Self {
879            column,
880            memory: column.memory,
881            stride: column.info.layout.size(),
882            left: size,
883            _phantom: PhantomData,
884        })
885    }
886}
887
888impl<'a, const LOCKING: bool, T: Component> Iterator for ArchetypeColumnWriteIter<'a, LOCKING, T> {
889    type Item = &'a mut T;
890
891    fn next(&mut self) -> Option<Self::Item> {
892        if self.left == 0 {
893            return None;
894        }
895        self.left -= 1;
896        unsafe {
897            let result = self.memory.cast::<T>().as_mut()?;
898            self.memory = self.memory.add(self.stride);
899            Some(result)
900        }
901    }
902
903    fn size_hint(&self) -> (usize, Option<usize>) {
904        (self.left, Some(self.left))
905    }
906}
907
908pub struct ArchetypeDynamicColumnItem<'a> {
909    memory: *mut u8,
910    type_hash: TypeHash,
911    unique: bool,
912    _phantom: PhantomData<&'a ()>,
913}
914
915impl ArchetypeDynamicColumnItem<'_> {
916    pub fn is_unique(&self) -> bool {
917        self.unique
918    }
919
920    pub fn type_hash(&self) -> TypeHash {
921        self.type_hash
922    }
923
924    /// # Safety
925    pub unsafe fn data(&self) -> *mut u8 {
926        self.memory
927    }
928
929    pub fn read<T: Component>(&self) -> Option<&T> {
930        if self.type_hash == TypeHash::of::<T>() {
931            unsafe { self.memory.cast::<T>().as_ref() }
932        } else {
933            None
934        }
935    }
936
937    pub fn write<T: Component>(&mut self) -> Option<&mut T> {
938        if self.unique && self.type_hash == TypeHash::of::<T>() {
939            unsafe { self.memory.cast::<T>().as_mut() }
940        } else {
941            None
942        }
943    }
944}
945
946pub struct ArchetypeDynamicColumnIter<'a, const LOCKING: bool> {
947    column: &'a Column,
948    memory: *mut u8,
949    type_hash: TypeHash,
950    stride: usize,
951    left: usize,
952    unique: bool,
953}
954
955impl<const LOCKING: bool> Drop for ArchetypeDynamicColumnIter<'_, LOCKING> {
956    fn drop(&mut self) {
957        if self.unique {
958            if LOCKING {
959                while self
960                    .column
961                    .unique_access
962                    .compare_exchange_weak(true, false, Ordering::Acquire, Ordering::Relaxed)
963                    .is_err()
964                {
965                    traced_spin_loop();
966                }
967            } else {
968                let _ = self.column.unique_access.compare_exchange(
969                    true,
970                    false,
971                    Ordering::Acquire,
972                    Ordering::Relaxed,
973                );
974            }
975        }
976    }
977}
978
979impl<'a, const LOCKING: bool> ArchetypeDynamicColumnIter<'a, LOCKING> {
980    fn new(column: &'a Column, unique: bool, size: usize) -> Result<Self, ArchetypeError> {
981        if unique {
982            if LOCKING {
983                while column
984                    .unique_access
985                    .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
986                    .is_err()
987                {
988                    traced_spin_loop();
989                }
990            } else if column
991                .unique_access
992                .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
993                .is_err()
994            {
995                return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
996                    type_hash: column.info.type_hash,
997                });
998            }
999        } else if LOCKING {
1000            while column.unique_access.load(Ordering::Acquire) {
1001                traced_spin_loop();
1002            }
1003        } else if column.unique_access.load(Ordering::Acquire) {
1004            return Err(ArchetypeError::ColumnAlreadyUniquelyAccessed {
1005                type_hash: column.info.type_hash,
1006            });
1007        }
1008        Ok(Self {
1009            column,
1010            memory: column.memory,
1011            type_hash: column.info.type_hash,
1012            stride: column.info.layout.size(),
1013            left: size,
1014            unique,
1015        })
1016    }
1017}
1018
1019impl<'a, const LOCKING: bool> Iterator for ArchetypeDynamicColumnIter<'a, LOCKING> {
1020    type Item = ArchetypeDynamicColumnItem<'a>;
1021
1022    fn next(&mut self) -> Option<Self::Item> {
1023        if self.left == 0 {
1024            return None;
1025        }
1026        self.left -= 1;
1027        let result = ArchetypeDynamicColumnItem {
1028            memory: self.memory,
1029            type_hash: self.type_hash,
1030            unique: self.unique,
1031            _phantom: PhantomData,
1032        };
1033        self.memory = unsafe { self.memory.add(self.stride) };
1034        Some(result)
1035    }
1036
1037    fn size_hint(&self) -> (usize, Option<usize>) {
1038        (self.left, Some(self.left))
1039    }
1040}
1041
1042struct Column {
1043    memory: *mut u8,
1044    layout: Layout,
1045    info: ArchetypeColumnInfo,
1046    unique_access: Arc<AtomicBool>,
1047    instances: Arc<AtomicUsize>,
1048}
1049
1050unsafe impl Send for Column {}
1051unsafe impl Sync for Column {}
1052
1053impl Drop for Column {
1054    fn drop(&mut self) {
1055        if self.instances.fetch_sub(1, Ordering::SeqCst) <= 1 {
1056            while self.unique_access.load(Ordering::Acquire) {
1057                traced_spin_loop();
1058            }
1059            unsafe {
1060                non_zero_dealloc(self.memory, self.layout);
1061            }
1062        }
1063    }
1064}
1065
1066impl Clone for Column {
1067    fn clone(&self) -> Self {
1068        let instances = self.instances.clone();
1069        instances.fetch_add(1, Ordering::SeqCst);
1070        Self {
1071            memory: self.memory,
1072            layout: self.layout,
1073            info: self.info,
1074            unique_access: self.unique_access.clone(),
1075            instances,
1076        }
1077    }
1078}
1079
1080impl Column {
1081    fn new(info: ArchetypeColumnInfo, capacity: usize) -> Self {
1082        let (memory, layout) = unsafe { Self::allocate_memory(info.layout, capacity) };
1083        Self {
1084            memory,
1085            layout,
1086            info,
1087            unique_access: Default::default(),
1088            instances: Arc::new(AtomicUsize::new(1)),
1089        }
1090    }
1091
1092    pub fn validate_sdir(&self) -> Result<(), ArchetypeError> {
1093        if self.instances.load(Ordering::Acquire) <= 1 {
1094            Ok(())
1095        } else {
1096            Err(ArchetypeError::ColumnSdirLocked {
1097                type_hash: self.info.type_hash,
1098            })
1099        }
1100    }
1101
1102    unsafe fn reallocate(&mut self, size: usize, capacity: usize) {
1103        let info_layout = self.info.layout;
1104        let (memory, layout) = unsafe { Self::allocate_memory(info_layout, capacity) };
1105        unsafe { self.memory.copy_to(memory, info_layout.size() * size) };
1106        unsafe { non_zero_dealloc(self.memory, self.layout) };
1107        self.memory = memory;
1108        self.layout = layout;
1109    }
1110
1111    unsafe fn allocate_memory(item_layout: Layout, capacity: usize) -> (*mut u8, Layout) {
1112        let layout = unsafe {
1113            Layout::from_size_align_unchecked(item_layout.size() * capacity, item_layout.align())
1114        };
1115        let memory = unsafe { non_zero_alloc(layout) };
1116        (memory, layout)
1117    }
1118
1119    unsafe fn column_access<const LOCKING: bool, T: Component>(
1120        &'_ self,
1121        unique: bool,
1122        size: usize,
1123    ) -> Result<ArchetypeColumnAccess<'_, LOCKING, T>, ArchetypeError> {
1124        unsafe { ArchetypeColumnAccess::new(self, unique, size) }
1125    }
1126
1127    fn dynamic_column_access<const LOCKING: bool>(
1128        &'_ self,
1129        unique: bool,
1130        size: usize,
1131    ) -> Result<ArchetypeDynamicColumnAccess<'_, LOCKING>, ArchetypeError> {
1132        ArchetypeDynamicColumnAccess::new(self, unique, size)
1133    }
1134
1135    unsafe fn entity_access<const LOCKING: bool, T: Component>(
1136        &'_ self,
1137        unique: bool,
1138        index: usize,
1139    ) -> Result<ArchetypeEntityColumnAccess<'_, LOCKING, T>, ArchetypeError> {
1140        unsafe { ArchetypeEntityColumnAccess::new(self, unique, index) }
1141    }
1142
1143    fn dynamic_entity_access<const LOCKING: bool>(
1144        &'_ self,
1145        unique: bool,
1146        index: usize,
1147    ) -> Result<ArchetypeDynamicEntityColumnAccess<'_, LOCKING>, ArchetypeError> {
1148        ArchetypeDynamicEntityColumnAccess::new(self, unique, index)
1149    }
1150
1151    fn column_read_iter<const LOCKING: bool, T: Component>(
1152        &'_ self,
1153        size: usize,
1154    ) -> Result<ArchetypeColumnReadIter<'_, T>, ArchetypeError> {
1155        ArchetypeColumnReadIter::new::<LOCKING>(self, size)
1156    }
1157
1158    fn column_write_iter<const LOCKING: bool, T: Component>(
1159        &'_ self,
1160        size: usize,
1161    ) -> Result<ArchetypeColumnWriteIter<'_, LOCKING, T>, ArchetypeError> {
1162        ArchetypeColumnWriteIter::new(self, size)
1163    }
1164
1165    fn dynamic_column_iter<const LOCKING: bool>(
1166        &'_ self,
1167        unique: bool,
1168        size: usize,
1169    ) -> Result<ArchetypeDynamicColumnIter<'_, LOCKING>, ArchetypeError> {
1170        ArchetypeDynamicColumnIter::new(self, unique, size)
1171    }
1172}
1173
1174pub struct Archetype {
1175    columns: Box<[Column]>,
1176    capacity: usize,
1177    size: usize,
1178    entity_dense_map: EntityDenseMap,
1179}
1180
1181impl Drop for Archetype {
1182    fn drop(&mut self) {
1183        let _ = self.clear::<true>();
1184    }
1185}
1186
1187impl Archetype {
1188    pub fn new(
1189        columns: Vec<ArchetypeColumnInfo>,
1190        mut capacity: usize,
1191    ) -> Result<Self, ArchetypeError> {
1192        for (index, column) in columns.iter().enumerate() {
1193            let position = columns
1194                .iter()
1195                .position(|c| c.type_hash == column.type_hash)
1196                .unwrap();
1197            if position != index {
1198                return Err(ArchetypeError::ColumnTypeIsDuplicated {
1199                    type_hash: column.type_hash,
1200                    index,
1201                    duplicate_index: position,
1202                });
1203            }
1204        }
1205        capacity = capacity.next_power_of_two();
1206        let columns = columns
1207            .into_iter()
1208            .map(|info| Column::new(info, capacity))
1209            .collect::<Vec<_>>();
1210        // TODO: reorder to pack for minimal space gaps and compact layout.
1211        let columns = columns.into_boxed_slice();
1212        Ok(Self {
1213            columns,
1214            capacity,
1215            size: 0,
1216            entity_dense_map: Default::default(),
1217        })
1218    }
1219
1220    pub fn view<B: BundleColumns>(&self) -> Option<ArchetypeView> {
1221        let columns = B::columns_static()
1222            .into_iter()
1223            .filter_map(|info| {
1224                self.columns
1225                    .iter()
1226                    .find(|column| column.info == info)
1227                    .cloned()
1228            })
1229            .collect::<Vec<_>>();
1230        if columns.is_empty() {
1231            None
1232        } else {
1233            Some(ArchetypeView {
1234                archetype: Self {
1235                    columns: columns.into_boxed_slice(),
1236                    capacity: self.capacity,
1237                    size: self.size,
1238                    entity_dense_map: self.entity_dense_map.clone(),
1239                },
1240            })
1241        }
1242    }
1243
1244    pub fn view_raw(&self, columns: &[ArchetypeColumnInfo]) -> Option<ArchetypeView> {
1245        let columns = columns
1246            .iter()
1247            .filter_map(|info| {
1248                self.columns
1249                    .iter()
1250                    .find(|column| &column.info == info)
1251                    .cloned()
1252            })
1253            .collect::<Vec<_>>();
1254        if columns.is_empty() {
1255            None
1256        } else {
1257            Some(ArchetypeView {
1258                archetype: Self {
1259                    columns: columns.into_boxed_slice(),
1260                    capacity: self.capacity,
1261                    size: self.size,
1262                    entity_dense_map: self.entity_dense_map.clone(),
1263                },
1264            })
1265        }
1266    }
1267
1268    pub fn view_all(&self) -> ArchetypeView {
1269        ArchetypeView {
1270            archetype: Self {
1271                columns: self.columns.to_vec().into_boxed_slice(),
1272                capacity: self.capacity,
1273                size: self.size,
1274                entity_dense_map: self.entity_dense_map.clone(),
1275            },
1276        }
1277    }
1278
1279    pub fn validate_sdir(&self) -> Result<(), ArchetypeError> {
1280        for column in self.columns.as_ref() {
1281            column.validate_sdir()?;
1282        }
1283        Ok(())
1284    }
1285
1286    pub fn is_column_sdir_locked_raw(&self, type_hash: TypeHash) -> bool {
1287        self.columns
1288            .iter()
1289            .any(|column| column.info.type_hash == type_hash && column.validate_sdir().is_err())
1290    }
1291
1292    pub fn is_column_sdir_locked<T: Component>(&self) -> bool {
1293        self.is_column_sdir_locked_raw(TypeHash::of::<T>())
1294    }
1295
1296    #[inline]
1297    pub fn capacity(&self) -> usize {
1298        self.capacity
1299    }
1300
1301    #[inline]
1302    pub fn is_empty(&self) -> bool {
1303        self.size == 0
1304    }
1305
1306    #[inline]
1307    pub fn len(&self) -> usize {
1308        self.size
1309    }
1310
1311    #[inline]
1312    pub fn entities(&self) -> &EntityDenseMap {
1313        &self.entity_dense_map
1314    }
1315
1316    #[inline]
1317    pub fn columns(&self) -> impl Iterator<Item = &ArchetypeColumnInfo> {
1318        self.columns.as_ref().iter().map(|column| &column.info)
1319    }
1320
1321    pub fn has_column(&self, column: &ArchetypeColumnInfo) -> bool {
1322        self.columns
1323            .as_ref()
1324            .iter()
1325            .any(|c| column.type_hash == c.info.type_hash)
1326    }
1327
1328    pub fn has_columns(&self, columns: &[ArchetypeColumnInfo]) -> bool {
1329        columns.iter().all(|column| {
1330            self.columns
1331                .as_ref()
1332                .iter()
1333                .any(|c| column.type_hash == c.info.type_hash)
1334        })
1335    }
1336
1337    pub fn has_columns_exact(&self, columns: &[ArchetypeColumnInfo]) -> bool {
1338        self.columns.as_ref().len() == columns.len() && self.has_columns(columns)
1339    }
1340
1341    pub fn has_any_columns(&self, columns: &[ArchetypeColumnInfo]) -> bool {
1342        columns.iter().any(|column| {
1343            self.columns
1344                .as_ref()
1345                .iter()
1346                .any(|c| column.type_hash == c.info.type_hash)
1347        })
1348    }
1349
1350    pub fn has_no_columns(&self, columns: &[ArchetypeColumnInfo]) -> bool {
1351        !columns.iter().any(|column| {
1352            self.columns
1353                .as_ref()
1354                .iter()
1355                .any(|c| column.type_hash == c.info.type_hash)
1356        })
1357    }
1358
1359    pub fn has_type(&self, type_hash: TypeHash) -> bool {
1360        self.columns
1361            .as_ref()
1362            .iter()
1363            .any(|c| type_hash == c.info.type_hash)
1364    }
1365
1366    pub fn has_types(&self, types: &[TypeHash]) -> bool {
1367        types.iter().all(|type_hash| {
1368            self.columns
1369                .as_ref()
1370                .iter()
1371                .any(|c| type_hash == &c.info.type_hash)
1372        })
1373    }
1374
1375    pub fn has_types_exact(&self, types: &[TypeHash]) -> bool {
1376        self.columns.as_ref().len() == types.len() && self.has_types(types)
1377    }
1378
1379    pub fn has_no_types(&self, types: &[TypeHash]) -> bool {
1380        !types.iter().any(|type_hash| {
1381            self.columns
1382                .as_ref()
1383                .iter()
1384                .any(|c| type_hash == &c.info.type_hash)
1385        })
1386    }
1387
1388    pub fn clear<const LOCKING: bool>(&mut self) -> Result<(), ArchetypeError> {
1389        self.validate_sdir()?;
1390        let access = self
1391            .columns
1392            .as_ref()
1393            .iter()
1394            .map(|column| column.dynamic_column_access::<LOCKING>(true, self.size))
1395            .collect::<Result<Vec<_>, _>>()?;
1396        for access in access {
1397            for index in 0..access.size() {
1398                unsafe {
1399                    (access.info().finalizer())(access.data(index).unwrap().cast());
1400                }
1401            }
1402        }
1403        self.size = 0;
1404        self.entity_dense_map.clear();
1405        Ok(())
1406    }
1407
1408    /// # Safety
1409    pub(crate) unsafe fn clear_uninitialized(&mut self) {
1410        // TODO: consider SDIR validation if it makes sense in where is it called.
1411        self.size = 0;
1412        self.entity_dense_map.clear();
1413    }
1414
1415    fn ensure_columns_capacity(&mut self, new_size: usize) {
1416        if new_size <= self.capacity {
1417            return;
1418        }
1419        while new_size > self.capacity {
1420            self.capacity *= 2;
1421        }
1422        for column in self.columns.as_mut() {
1423            unsafe { column.reallocate(self.size, self.capacity) };
1424        }
1425    }
1426
1427    pub fn insert(&mut self, entity: Entity, bundle: impl Bundle) -> Result<(), ArchetypeError> {
1428        self.validate_sdir()?;
1429        for info in bundle.columns() {
1430            if !self
1431                .columns
1432                .as_ref()
1433                .iter()
1434                .any(|column| column.info.type_hash == info.type_hash)
1435            {
1436                return Err(ArchetypeError::ColumnNotFound {
1437                    type_hash: info.type_hash,
1438                });
1439            }
1440        }
1441        self.ensure_columns_capacity(self.size + 1);
1442        let index = match self.entity_dense_map.insert(entity) {
1443            Ok(index) => index,
1444            Err(index) => return Err(ArchetypeError::IndexAlreadyOccupied { index }),
1445        };
1446        let access = ArchetypeEntityRowAccess::new(
1447            self.columns
1448                .as_ref()
1449                .iter()
1450                .collect::<Vec<_>>()
1451                .into_boxed_slice(),
1452            index,
1453        );
1454        bundle.initialize_into(&access);
1455        self.size += 1;
1456        Ok(())
1457    }
1458
1459    pub fn add(
1460        &'_ mut self,
1461        entity: Entity,
1462    ) -> Result<ArchetypeEntityRowAccess<'_>, ArchetypeError> {
1463        self.validate_sdir()?;
1464        self.ensure_columns_capacity(self.size + 1);
1465        let index = match self.entity_dense_map.insert(entity) {
1466            Ok(index) => index,
1467            Err(index) => return Err(ArchetypeError::IndexAlreadyOccupied { index }),
1468        };
1469        self.size += 1;
1470        Ok(ArchetypeEntityRowAccess::new(
1471            self.columns
1472                .as_ref()
1473                .iter()
1474                .collect::<Vec<_>>()
1475                .into_boxed_slice(),
1476            index,
1477        ))
1478    }
1479
1480    pub fn remove(&mut self, entity: Entity) -> Result<(), ArchetypeError> {
1481        if self.size == 0 {
1482            return Err(ArchetypeError::EntityNotFound { entity });
1483        }
1484        self.validate_sdir()?;
1485        let index = self
1486            .entity_dense_map
1487            .remove(entity)
1488            .ok_or(ArchetypeError::EntityNotFound { entity })?;
1489        self.size -= 1;
1490        for column in self.columns.as_ref() {
1491            unsafe {
1492                let target = column.memory.add(index * column.info.layout.size());
1493                (column.info.finalizer)(target.cast());
1494                if self.size != index {
1495                    let source = column.memory.add(self.size * column.info.layout.size());
1496                    source.copy_to(target, column.info.layout.size());
1497                }
1498            }
1499        }
1500        Ok(())
1501    }
1502
1503    /// # Safety
1504    pub unsafe fn remove_uninitialized(&mut self, entity: Entity) -> Result<(), ArchetypeError> {
1505        if self.size == 0 {
1506            return Err(ArchetypeError::EntityNotFound { entity });
1507        }
1508        self.validate_sdir()?;
1509        let index = self
1510            .entity_dense_map
1511            .remove(entity)
1512            .ok_or(ArchetypeError::EntityNotFound { entity })?;
1513        self.size -= 1;
1514        for column in self.columns.as_ref() {
1515            unsafe {
1516                let target = column.memory.add(index * column.info.layout.size());
1517                if self.size != index {
1518                    let source = column.memory.add(self.size * column.info.layout.size());
1519                    source.copy_to(target, column.info.layout.size());
1520                }
1521            }
1522        }
1523        Ok(())
1524    }
1525
1526    pub fn transfer<'a>(
1527        &mut self,
1528        other: &'a mut Self,
1529        entity: Entity,
1530    ) -> Result<ArchetypeEntityRowAccess<'a>, ArchetypeError> {
1531        if self.size == 0 || !self.entity_dense_map.contains(entity) {
1532            return Err(ArchetypeError::EntityNotFound { entity });
1533        }
1534        if other.entity_dense_map.contains(entity) {
1535            return Err(ArchetypeError::EntityAlreadyOccupied { entity });
1536        }
1537        self.validate_sdir()?;
1538        other.ensure_columns_capacity(other.size + 1);
1539        let index_to = other.entity_dense_map.insert(entity).unwrap();
1540        let index_from = self.entity_dense_map.remove(entity).unwrap();
1541        let columns = other
1542            .columns
1543            .as_ref()
1544            .iter()
1545            .filter(|column| {
1546                !self
1547                    .columns
1548                    .as_ref()
1549                    .iter()
1550                    .any(|c| column.info.type_hash == c.info.type_hash)
1551            })
1552            .collect::<Vec<_>>();
1553        let to_initialize = ArchetypeEntityRowAccess::new(columns.into_boxed_slice(), index_to);
1554        let columns = self
1555            .columns
1556            .as_ref()
1557            .iter()
1558            .filter(|column| {
1559                !other
1560                    .columns
1561                    .as_ref()
1562                    .iter()
1563                    .any(|c| column.info.type_hash == c.info.type_hash)
1564            })
1565            .collect::<Vec<_>>();
1566        let to_finalize = ArchetypeEntityRowAccess::new(columns.into_boxed_slice(), index_from);
1567        self.size -= 1;
1568        other.size += 1;
1569        let (to_move_from, to_move_to): (Vec<_>, Vec<_>) = self
1570            .columns
1571            .as_ref()
1572            .iter()
1573            .filter_map(|column| {
1574                let c = other
1575                    .columns
1576                    .as_ref()
1577                    .iter()
1578                    .find(|c| column.info.type_hash == c.info.type_hash)?;
1579                Some((column, c))
1580            })
1581            .unzip();
1582        let to_move_from =
1583            ArchetypeEntityRowAccess::new(to_move_from.into_boxed_slice(), index_from);
1584        let to_move_to = ArchetypeEntityRowAccess::new(to_move_to.into_boxed_slice(), index_to);
1585        for (from, to) in to_move_from
1586            .columns
1587            .as_ref()
1588            .iter()
1589            .zip(to_move_to.columns.as_ref().iter())
1590        {
1591            unsafe {
1592                let source = from.memory.add(index_from * from.info.layout.size());
1593                let target = to.memory.add(index_to * to.info.layout.size());
1594                source.copy_to(target, from.info.layout.size());
1595            }
1596        }
1597        for column in to_finalize.columns.as_ref() {
1598            unsafe {
1599                let data = column.memory.add(index_from * column.info.layout.size());
1600                (column.info.finalizer)(data.cast());
1601            }
1602        }
1603        if index_from < self.size {
1604            for column in self.columns.as_ref().iter() {
1605                unsafe {
1606                    let source = column.memory.add(self.size * column.info.layout.size());
1607                    let target = column.memory.add(index_from * column.info.layout.size());
1608                    source.copy_to(target, column.info.layout.size());
1609                }
1610            }
1611        }
1612        Ok(to_initialize)
1613    }
1614
1615    pub fn column<const LOCKING: bool, T: Component>(
1616        &'_ self,
1617        unique: bool,
1618    ) -> Result<ArchetypeColumnAccess<'_, LOCKING, T>, ArchetypeError> {
1619        let type_hash = TypeHash::of::<T>();
1620        for column in self.columns.as_ref() {
1621            if column.info.type_hash == type_hash {
1622                return unsafe { column.column_access::<LOCKING, T>(unique, self.size) };
1623            }
1624        }
1625        Err(ArchetypeError::ColumnNotFound { type_hash })
1626    }
1627
1628    pub fn dynamic_column<const LOCKING: bool>(
1629        &'_ self,
1630        type_hash: TypeHash,
1631        unique: bool,
1632    ) -> Result<ArchetypeDynamicColumnAccess<'_, LOCKING>, ArchetypeError> {
1633        for column in self.columns.as_ref() {
1634            if column.info.type_hash == type_hash {
1635                return column.dynamic_column_access(unique, self.size);
1636            }
1637        }
1638        Err(ArchetypeError::ColumnNotFound { type_hash })
1639    }
1640
1641    pub fn entity<const LOCKING: bool, T: Component>(
1642        &'_ self,
1643        entity: Entity,
1644        unique: bool,
1645    ) -> Result<ArchetypeEntityColumnAccess<'_, LOCKING, T>, ArchetypeError> {
1646        let type_hash = TypeHash::of::<T>();
1647        let index = self
1648            .entity_dense_map
1649            .index_of(entity)
1650            .ok_or(ArchetypeError::EntityNotFound { entity })?;
1651        for column in self.columns.as_ref() {
1652            if column.info.type_hash == type_hash {
1653                return unsafe { column.entity_access::<LOCKING, T>(unique, index) };
1654            }
1655        }
1656        Err(ArchetypeError::ColumnNotFound { type_hash })
1657    }
1658
1659    pub fn dynamic_entity<const LOCKING: bool>(
1660        &'_ self,
1661        type_hash: TypeHash,
1662        entity: Entity,
1663        unique: bool,
1664    ) -> Result<ArchetypeDynamicEntityColumnAccess<'_, LOCKING>, ArchetypeError> {
1665        let index = self
1666            .entity_dense_map
1667            .index_of(entity)
1668            .ok_or(ArchetypeError::EntityNotFound { entity })?;
1669        for column in self.columns.as_ref() {
1670            if column.info.type_hash == type_hash {
1671                return column.dynamic_entity_access(unique, index);
1672            }
1673        }
1674        Err(ArchetypeError::ColumnNotFound { type_hash })
1675    }
1676
1677    pub fn row<const LOCKING: bool>(
1678        &'_ self,
1679        entity: Entity,
1680    ) -> Result<ArchetypeEntityRowAccess<'_>, ArchetypeError> {
1681        let index = self
1682            .entity_dense_map
1683            .index_of(entity)
1684            .ok_or(ArchetypeError::EntityNotFound { entity })?;
1685        Ok(ArchetypeEntityRowAccess::new(
1686            self.columns
1687                .as_ref()
1688                .iter()
1689                .collect::<Vec<_>>()
1690                .into_boxed_slice(),
1691            index,
1692        ))
1693    }
1694
1695    pub fn column_read_iter<const LOCKING: bool, T: Component>(
1696        &'_ self,
1697    ) -> Result<ArchetypeColumnReadIter<'_, T>, ArchetypeError> {
1698        let type_hash = TypeHash::of::<T>();
1699        for column in self.columns.as_ref() {
1700            if column.info.type_hash == type_hash {
1701                return column.column_read_iter::<LOCKING, T>(self.size);
1702            }
1703        }
1704        Err(ArchetypeError::ColumnNotFound { type_hash })
1705    }
1706
1707    pub fn column_write_iter<const LOCKING: bool, T: Component>(
1708        &'_ self,
1709    ) -> Result<ArchetypeColumnWriteIter<'_, LOCKING, T>, ArchetypeError> {
1710        let type_hash = TypeHash::of::<T>();
1711        for column in self.columns.as_ref() {
1712            if column.info.type_hash == type_hash {
1713                return column.column_write_iter::<LOCKING, T>(self.size);
1714            }
1715        }
1716        Err(ArchetypeError::ColumnNotFound { type_hash })
1717    }
1718
1719    pub fn dynamic_column_iter<const LOCKING: bool>(
1720        &'_ self,
1721        type_hash: TypeHash,
1722        unique: bool,
1723    ) -> Result<ArchetypeDynamicColumnIter<'_, LOCKING>, ArchetypeError> {
1724        for column in self.columns.as_ref() {
1725            if column.info.type_hash == type_hash {
1726                return column.dynamic_column_iter(unique, self.size);
1727            }
1728        }
1729        Err(ArchetypeError::ColumnNotFound { type_hash })
1730    }
1731}
1732
1733pub struct ArchetypeView {
1734    archetype: Archetype,
1735}
1736
1737impl ArchetypeView {
1738    pub fn view<B: BundleColumns>(&self) -> Option<ArchetypeView> {
1739        self.archetype.view::<B>()
1740    }
1741
1742    pub fn archetype(&self) -> &Archetype {
1743        &self.archetype
1744    }
1745
1746    #[inline]
1747    pub fn capacity(&self) -> usize {
1748        self.archetype.capacity()
1749    }
1750
1751    #[inline]
1752    pub fn is_empty(&self) -> bool {
1753        self.archetype.is_empty()
1754    }
1755
1756    #[inline]
1757    pub fn len(&self) -> usize {
1758        self.archetype.len()
1759    }
1760
1761    #[inline]
1762    pub fn entities(&self) -> &EntityDenseMap {
1763        self.archetype.entities()
1764    }
1765
1766    #[inline]
1767    pub fn columns(&self) -> impl Iterator<Item = &ArchetypeColumnInfo> {
1768        self.archetype.columns()
1769    }
1770
1771    pub fn has_column(&self, column: &ArchetypeColumnInfo) -> bool {
1772        self.archetype.has_column(column)
1773    }
1774
1775    pub fn has_columns(&self, columns: &[ArchetypeColumnInfo]) -> bool {
1776        self.archetype.has_columns(columns)
1777    }
1778
1779    pub fn has_columns_exact(&self, columns: &[ArchetypeColumnInfo]) -> bool {
1780        self.archetype.has_columns_exact(columns)
1781    }
1782
1783    pub fn has_any_columns(&self, columns: &[ArchetypeColumnInfo]) -> bool {
1784        self.archetype.has_any_columns(columns)
1785    }
1786
1787    pub fn has_no_columns(&self, columns: &[ArchetypeColumnInfo]) -> bool {
1788        self.archetype.has_no_columns(columns)
1789    }
1790
1791    pub fn has_type(&self, type_hash: TypeHash) -> bool {
1792        self.archetype.has_type(type_hash)
1793    }
1794
1795    pub fn has_types(&self, types: &[TypeHash]) -> bool {
1796        self.archetype.has_types(types)
1797    }
1798
1799    pub fn has_types_exact(&self, types: &[TypeHash]) -> bool {
1800        self.archetype.has_types_exact(types)
1801    }
1802
1803    pub fn has_no_types(&self, types: &[TypeHash]) -> bool {
1804        self.archetype.has_no_types(types)
1805    }
1806
1807    pub fn column<const LOCKING: bool, T: Component>(
1808        &'_ self,
1809        unique: bool,
1810    ) -> Result<ArchetypeColumnAccess<'_, LOCKING, T>, ArchetypeError> {
1811        self.archetype.column::<LOCKING, T>(unique)
1812    }
1813
1814    pub fn dynamic_column<const LOCKING: bool>(
1815        &'_ self,
1816        type_hash: TypeHash,
1817        unique: bool,
1818    ) -> Result<ArchetypeDynamicColumnAccess<'_, LOCKING>, ArchetypeError> {
1819        self.archetype.dynamic_column::<LOCKING>(type_hash, unique)
1820    }
1821
1822    pub fn entity<const LOCKING: bool, T: Component>(
1823        &'_ self,
1824        entity: Entity,
1825        unique: bool,
1826    ) -> Result<ArchetypeEntityColumnAccess<'_, LOCKING, T>, ArchetypeError> {
1827        self.archetype.entity::<LOCKING, T>(entity, unique)
1828    }
1829
1830    pub fn dynamic_entity<const LOCKING: bool>(
1831        &'_ self,
1832        type_hash: TypeHash,
1833        entity: Entity,
1834        unique: bool,
1835    ) -> Result<ArchetypeDynamicEntityColumnAccess<'_, LOCKING>, ArchetypeError> {
1836        self.archetype
1837            .dynamic_entity::<LOCKING>(type_hash, entity, unique)
1838    }
1839
1840    pub fn row<const LOCKING: bool>(
1841        &'_ self,
1842        entity: Entity,
1843    ) -> Result<ArchetypeEntityRowAccess<'_>, ArchetypeError> {
1844        self.archetype.row::<LOCKING>(entity)
1845    }
1846
1847    pub fn column_read_iter<const LOCKING: bool, T: Component>(
1848        &'_ self,
1849    ) -> Result<ArchetypeColumnReadIter<'_, T>, ArchetypeError> {
1850        self.archetype.column_read_iter::<LOCKING, T>()
1851    }
1852
1853    pub fn column_write_iter<const LOCKING: bool, T: Component>(
1854        &'_ self,
1855    ) -> Result<ArchetypeColumnWriteIter<'_, LOCKING, T>, ArchetypeError> {
1856        self.archetype.column_write_iter::<LOCKING, T>()
1857    }
1858
1859    pub fn dynamic_column_iter<const LOCKING: bool>(
1860        &'_ self,
1861        type_hash: TypeHash,
1862        unique: bool,
1863    ) -> Result<ArchetypeDynamicColumnIter<'_, LOCKING>, ArchetypeError> {
1864        self.archetype
1865            .dynamic_column_iter::<LOCKING>(type_hash, unique)
1866    }
1867}
1868
1869impl Clone for ArchetypeView {
1870    fn clone(&self) -> Self {
1871        self.archetype.view_all()
1872    }
1873}
1874
1875#[cfg(test)]
1876mod tests {
1877    use super::*;
1878    use std::sync::{Arc, RwLock};
1879
1880    #[test]
1881    fn test_archetype_changes() {
1882        let entity = Entity::new(0, 0).unwrap();
1883        let mut a = Archetype::new(vec![ArchetypeColumnInfo::new::<u8>()], 2).unwrap();
1884        assert!(a.is_empty());
1885        assert_eq!(a.capacity(), 2);
1886        assert!(!a.entities().contains(entity));
1887
1888        a.insert(entity, (1u8,)).unwrap();
1889        assert_eq!(a.len(), 1);
1890        assert_eq!(a.capacity(), 2);
1891        assert!(a.entities().contains(entity));
1892
1893        a.remove(entity).unwrap();
1894        assert!(a.is_empty());
1895        assert_eq!(a.capacity(), 2);
1896        assert!(!a.entities().contains(entity));
1897
1898        let access = a.add(entity).unwrap();
1899        unsafe { access.initialize(1u8).unwrap() };
1900        drop(access);
1901        assert_eq!(
1902            *a.entity::<true, u8>(entity, false).unwrap().read().unwrap(),
1903            1
1904        );
1905
1906        let mut b = Archetype::new(
1907            vec![
1908                ArchetypeColumnInfo::new::<u8>(),
1909                ArchetypeColumnInfo::new::<u16>(),
1910            ],
1911            2,
1912        )
1913        .unwrap();
1914        let access = a.transfer(&mut b, entity).unwrap();
1915        unsafe { access.initialize(2u16).unwrap() };
1916        assert_eq!(access.len(), 1);
1917        drop(access);
1918        assert!(a.is_empty());
1919        assert_eq!(a.capacity(), 2);
1920        assert!(!a.entities().contains(entity));
1921        assert_eq!(b.len(), 1);
1922        assert_eq!(b.capacity(), 2);
1923        assert!(b.entities().contains(entity));
1924        assert_eq!(
1925            *b.entity::<true, u8>(entity, false).unwrap().read().unwrap(),
1926            1
1927        );
1928        assert_eq!(
1929            *b.entity::<true, u16>(entity, false)
1930                .unwrap()
1931                .read()
1932                .unwrap(),
1933            2
1934        );
1935
1936        let mut c = Archetype::new(vec![ArchetypeColumnInfo::new::<u16>()], 2).unwrap();
1937        let access = b.transfer(&mut c, entity).unwrap();
1938        assert_eq!(access.len(), 0);
1939        drop(access);
1940        assert!(b.is_empty());
1941        assert_eq!(b.capacity(), 2);
1942        assert!(!b.entities().contains(entity));
1943        assert_eq!(c.len(), 1);
1944        assert_eq!(c.capacity(), 2);
1945        assert!(c.entities().contains(entity));
1946        assert_eq!(
1947            *c.entity::<true, u16>(entity, false)
1948                .unwrap()
1949                .read()
1950                .unwrap(),
1951            2
1952        );
1953
1954        struct Droppable(Arc<RwLock<bool>>);
1955
1956        impl Drop for Droppable {
1957            fn drop(&mut self) {
1958                *self.0.write().unwrap() = true;
1959            }
1960        }
1961
1962        let mut d = Archetype::new(vec![ArchetypeColumnInfo::new::<Droppable>()], 1).unwrap();
1963        let dropped = Arc::new(RwLock::new(false));
1964        d.insert(entity, (Droppable(dropped.clone()),)).unwrap();
1965        assert!(!*dropped.read().unwrap());
1966        d.remove(entity).unwrap();
1967        assert!(*dropped.read().unwrap());
1968    }
1969
1970    #[test]
1971    fn test_archetype_iter() {
1972        let mut archetype = Archetype::new(
1973            vec![
1974                ArchetypeColumnInfo::new::<u8>(),
1975                ArchetypeColumnInfo::new::<u16>(),
1976            ],
1977            5,
1978        )
1979        .unwrap();
1980
1981        for index in 0..5 {
1982            archetype
1983                .insert(Entity::new(index, 0).unwrap(), (index as u8, index as u16))
1984                .unwrap();
1985        }
1986
1987        let iter = archetype.column_read_iter::<true, u8>().unwrap();
1988        assert_eq!(iter.size_hint(), (5, Some(5)));
1989        for (index, item) in iter.enumerate() {
1990            assert_eq!(*item, index as u8);
1991        }
1992
1993        let iter = archetype.column_write_iter::<true, u16>().unwrap();
1994        assert_eq!(iter.size_hint(), (5, Some(5)));
1995        for (index, item) in iter.enumerate() {
1996            assert_eq!(*item, index as u16);
1997            *item *= 10;
1998        }
1999
2000        let iter = archetype
2001            .dynamic_column_iter::<true>(TypeHash::of::<u16>(), false)
2002            .unwrap();
2003        assert_eq!(iter.size_hint(), (5, Some(5)));
2004        for (index, item) in iter.enumerate() {
2005            assert_eq!(*item.read::<u16>().unwrap(), index as u16 * 10);
2006        }
2007    }
2008}