my_ecs/default/
ent_cont.rs

1//! Provides [`ContainEntity`] implementations.
2//!
3//! Currently, there are two options.
4//!
5//! - [`SparseSet`] based on [`AnyVec`], which stores data serially. It's good
6//!   for traversing items, but requires copy when the vector needs to extend
7//!   its capacity.
8//!
9//! - [`ChunkSparseSet`] based on [`ChunkAnyVec`], which stores data in chunks.
10//!   Chunk is a fixed sized memory, and the vector appends a chunk when it
11//!   needs more capacity. Therefore, `ChunkSparseSet` is good for frequent
12//!   insertion or removal, but not good as mush as `SparseSet` in terms of
13//!   traversing items.
14
15use crate::{
16    ds::{
17        AnyVec, AsFlatRawIter, BorrowError, BorrowResult, ChunkAnyVec, FlatRawIter, Holder, OptVec,
18        RawGetter, TypeInfo,
19    },
20    ecs::ent::entity::{AddEntity, BorrowComponent, ContainEntity, RegisterComponent},
21};
22use std::{
23    any::TypeId, cmp, collections::HashMap, fmt::Debug, hash::BuildHasher, mem, ptr::NonNull,
24};
25
26/// Two-dimensional storage containing heterogeneous data types based on
27/// [`ChunkAnyVec`].
28///
29/// Unlike `SparseSet`, this struct stores data in chunks. Chunk is a fixed
30/// sized memory, and it's appended when extra capacity is needed. This chunk
31/// based capacity control removes data copy that is seen from normal vector,
32/// but note that it brings inefficiency in terms of iteration.
33///
34/// See [`SparseSet`] for more details.
35#[derive(Debug)]
36pub struct ChunkSparseSet<S> {
37    sparse: OptVec<usize, S>,
38    deref: Vec<usize>,
39    cols: Vec<Holder<ChunkAnyVec, RawGetter, RawGetter>>,
40    map: HashMap<TypeId, usize, S>,
41}
42
43impl<S> ChunkSparseSet<S>
44where
45    S: Default,
46{
47    const CHUNK_SIZE: usize = 4 * 1024;
48    const MIN_CHUNK_LEN: usize = 8;
49
50    /// Creates a new empty [`ChunkSparseSet`].
51    ///
52    /// # Examples
53    ///
54    /// ```
55    /// # use my_ecs::prelude::*;
56    ///
57    /// let mut cont = ChunkSparseSet::<std::hash::RandomState>::new();
58    /// ```
59    pub fn new() -> Self {
60        Self {
61            sparse: OptVec::new(),
62            deref: Vec::new(),
63            cols: Vec::new(),
64            map: HashMap::default(),
65        }
66    }
67}
68
69impl<S> ContainEntity for ChunkSparseSet<S>
70where
71    S: BuildHasher + Default + Clone + 'static,
72{
73    fn create_twin(&self) -> Box<dyn ContainEntity> {
74        // Creates new `Holder`s for the same types.
75        let cols = self
76            .cols
77            .iter()
78            .map(|col| {
79                let (fn_imm, fn_mut) = (col.get_fn_imm(), col.get_fn_mut());
80                let col = col.get().unwrap();
81                let value = ChunkAnyVec::new(*col.type_info(), col.default_chunk_capacity());
82                // Safety: It's safe to create the same `Holder`. The safety
83                // must have been guaranteed by source `Holder`.
84                unsafe { Holder::new(value, fn_imm, fn_mut) }
85            })
86            .collect::<Vec<_>>();
87
88        // We can reuse mapping information.
89        let map = self.map.clone();
90
91        // Makes empty instance.
92        let this = Self {
93            sparse: OptVec::new(),
94            deref: Vec::new(),
95            cols,
96            map,
97        };
98        Box::new(this)
99    }
100
101    fn get_item_mut(&mut self, ci: usize, ri: usize) -> Option<NonNull<u8>> {
102        let key = ri;
103
104        let index = *self.sparse.get(key)?;
105        let col = self.cols.get_mut(ci)?;
106        let col = col.get_mut().unwrap();
107        col.get_raw(index)
108    }
109
110    fn len(&self) -> usize {
111        // All columns must have the same length.
112        self.cols
113            .first()
114            .map(|col| unsafe { col.get_unchecked().len() })
115            .unwrap_or_default()
116    }
117
118    fn capacity(&self) -> usize {
119        // All columns must have the same length.
120        self.cols
121            .first()
122            .map(|col| unsafe { col.get_unchecked().capacity() })
123            .unwrap_or_default()
124    }
125
126    fn reserve(&mut self, additional: usize) {
127        for col in self.cols.iter_mut() {
128            col.get_mut().unwrap().reserve(additional);
129        }
130    }
131
132    fn shrink_to_fit(&mut self) {
133        for col in self.cols.iter_mut() {
134            col.get_mut().unwrap().shrink_to_fit();
135        }
136    }
137
138    unsafe fn resize_column(&mut self, ci: usize, new_len: usize, val_ptr: NonNull<u8>) {
139        let mut col = self.cols[ci].get_mut().unwrap();
140        assert!(col.is_clone());
141        unsafe { col.resize_raw(new_len, val_ptr) }
142    }
143}
144
145impl<S> RegisterComponent for ChunkSparseSet<S>
146where
147    S: BuildHasher + Default + Clone + 'static,
148{
149    /// Adds a new column and returns column index.
150    fn add_column(&mut self, tinfo: TypeInfo) -> Option<usize> {
151        let ty = tinfo.ty;
152        if self.len() > 0 || self.get_column_index(&ty).is_some() {
153            return None;
154        }
155
156        // Holder's immutable access function.
157        fn fn_imm(col: &ChunkAnyVec) -> RawGetter {
158            // Safety: Infallible.
159            let this = unsafe { NonNull::new_unchecked((col as *const _ as *const u8).cast_mut()) };
160            let len = col.len();
161            unsafe fn fn_get(this: NonNull<u8>, index: usize) -> NonNull<u8> {
162                unsafe { this.cast::<ChunkAnyVec>().as_ref().get_raw_unchecked(index) }
163            }
164            unsafe fn fn_iter(this: NonNull<u8>) -> FlatRawIter {
165                unsafe { this.cast::<ChunkAnyVec>().as_ref().iter() }
166            }
167            // Safety: The pointer is valid.
168            let getter = unsafe { RawGetter::new(this, len, fn_get) };
169            getter.with_iter(fn_iter)
170        }
171
172        // Holder's mutable access function.
173        fn fn_mut(col: &mut ChunkAnyVec) -> RawGetter {
174            fn_imm(col)
175        }
176
177        // Adds column wrapped with Holder.
178        let chunk_len = if tinfo.size != 0 {
179            cmp::max(
180                (Self::CHUNK_SIZE / tinfo.size).next_power_of_two(),
181                Self::MIN_CHUNK_LEN,
182            )
183        } else {
184            0 // Has no effect
185        };
186        let value = ChunkAnyVec::new(tinfo, chunk_len);
187        // Safety: `fn_imm` and `fn_mut` don't return lifetime-constrained type.
188        let holder = unsafe { Holder::new(value, fn_imm, fn_mut) };
189        self.cols.push(holder);
190
191        let ci = self.cols.len() - 1;
192        self.map.insert(ty, ci);
193        Some(ci)
194    }
195
196    fn remove_column(&mut self, ci: usize) -> Option<TypeInfo> {
197        if ci >= self.num_columns() || self.cols[ci].borrow_count() != 0 {
198            return None;
199        }
200
201        let old = self.cols.remove(ci);
202
203        // Does re-mapping.
204        for i in ci..self.cols.len() {
205            let col = self.cols[i].get().unwrap();
206            let ty = col.type_id();
207            *self.map.get_mut(&ty).unwrap() = i;
208        }
209
210        // If empty, initialize self completely.
211        if self.cols.is_empty() {
212            mem::take(self);
213        }
214
215        let old = old.get().unwrap();
216        let tinfo = old.type_info();
217        Some(*tinfo)
218    }
219
220    fn get_column_index(&self, ty: &TypeId) -> Option<usize> {
221        self.map.get(ty).cloned()
222    }
223
224    fn get_column_info(&self, ci: usize) -> Option<&TypeInfo> {
225        self.cols.get(ci).map(|col| {
226            let col = col.get().unwrap();
227            col.type_info()
228        })
229    }
230
231    fn num_columns(&self) -> usize {
232        self.cols.len()
233    }
234
235    fn contains_column(&self, ty: &TypeId) -> bool {
236        self.map.contains_key(ty)
237    }
238}
239
240impl<S> BorrowComponent for ChunkSparseSet<S>
241where
242    S: BuildHasher + Default + Clone + 'static,
243{
244    fn borrow_column(&self, ci: usize) -> BorrowResult<RawGetter> {
245        #[cfg(feature = "check")]
246        let this_len = self.len();
247
248        if let Some(col) = self.cols.get(ci) {
249            let borrowed = col.borrow();
250
251            // Validates length.
252            #[cfg(feature = "check")]
253            {
254                if let Ok(borrowed) = borrowed.as_ref() {
255                    assert_eq!(
256                        this_len,
257                        borrowed.len(),
258                        "borrowed column must have the same length as entity container's"
259                    );
260                }
261            }
262
263            borrowed
264        } else {
265            Err(BorrowError::OutOfBound)
266        }
267    }
268
269    fn borrow_column_mut(&mut self, ci: usize) -> BorrowResult<RawGetter> {
270        #[cfg(feature = "check")]
271        let this_len = self.len();
272
273        if let Some(col) = self.cols.get_mut(ci) {
274            let borrowed = col.borrow_mut();
275
276            // Validates length.
277            #[cfg(feature = "check")]
278            {
279                if let Ok(borrowed) = borrowed.as_ref() {
280                    assert_eq!(
281                        this_len,
282                        borrowed.len(),
283                        "borrowed column must have the same length as entity container's"
284                    );
285                }
286            }
287
288            borrowed
289        } else {
290            Err(BorrowError::OutOfBound)
291        }
292    }
293
294    unsafe fn get_column(&self, ci: usize) -> Option<NonNull<u8>> {
295        self.cols.get(ci).map(|col| unsafe {
296            let ptr = col.get_unchecked() as *const _ as *const u8;
297            NonNull::new_unchecked(ptr.cast_mut())
298        })
299    }
300}
301
302impl<S> AddEntity for ChunkSparseSet<S>
303where
304    S: BuildHasher + Default + Clone + 'static,
305{
306    fn to_value_index(&self, ri: usize) -> Option<usize> {
307        let key = ri;
308
309        self.sparse.get(key).cloned()
310    }
311
312    fn begin_add_row(&mut self) {}
313
314    unsafe fn add_value(&mut self, ci: usize, val_ptr: NonNull<u8>) {
315        // Panics if holder has been borrowed and not returned yet.
316        unsafe {
317            let holder = self.cols.get_unchecked_mut(ci);
318            let mut col = holder.get_mut().unwrap_unchecked();
319            col.push_raw(val_ptr);
320        }
321    }
322
323    unsafe fn end_add_row(&mut self) -> usize {
324        let vi = self.deref.len();
325        let ri = self.sparse.add(vi);
326        self.deref.push(ri);
327        ri
328    }
329
330    fn value_ptr_by_value_index(&self, ci: usize, vi: usize) -> Option<NonNull<u8>> {
331        // Safety: Getting pointer is ok.
332        let col = unsafe { self.cols.get(ci)?.get_unchecked() };
333        col.get_raw(vi)
334    }
335
336    fn remove_row(&mut self, ri: usize) -> bool {
337        if let Some(vi) = self.to_value_index(ri) {
338            self.remove_row_by_value_index(vi);
339            true
340        } else {
341            false
342        }
343    }
344
345    fn remove_row_by_value_index(&mut self, vi: usize) {
346        unsafe {
347            self.begin_remove_row_by_value_index(vi);
348            for ci in 0..self.num_columns() {
349                self.drop_value_by_value_index(ci, vi);
350            }
351            self.end_remove_row_by_value_index(vi);
352        }
353    }
354
355    unsafe fn begin_remove_row_by_value_index(&mut self, vi: usize) {
356        assert!(vi < self.len());
357    }
358
359    unsafe fn remove_value_by_value_index(&mut self, ci: usize, vi: usize, buf: NonNull<u8>) {
360        let holder = unsafe { self.cols.get_unchecked_mut(ci) };
361        let mut col = holder.get_mut().unwrap();
362        unsafe { col.swap_remove_raw(vi, buf.as_ptr()) };
363    }
364
365    unsafe fn drop_value_by_value_index(&mut self, ci: usize, vi: usize) {
366        let holder = unsafe { self.cols.get_unchecked_mut(ci) };
367        let mut col = holder.get_mut().unwrap();
368        col.swap_remove_drop(vi);
369    }
370
371    unsafe fn forget_value_by_value_index(&mut self, ci: usize, vi: usize) {
372        let holder = unsafe { self.cols.get_unchecked_mut(ci) };
373        let mut col = holder.get_mut().unwrap();
374        col.swap_remove_forget(vi);
375    }
376
377    unsafe fn end_remove_row_by_value_index(&mut self, vi: usize) {
378        let ri = self.deref.swap_remove(vi);
379        let _vi = self.sparse.take(ri);
380        debug_assert_eq!(_vi, Some(vi));
381        if vi < self.deref.len() {
382            let moved_key = self.deref[vi];
383            *self.sparse.get_mut(moved_key).unwrap() = vi;
384        }
385    }
386}
387
388impl<S> Default for ChunkSparseSet<S>
389where
390    S: Default,
391{
392    fn default() -> Self {
393        Self::new()
394    }
395}
396
397/// Two-dimensional storage containing heterogeneous data types based on
398/// [`AnyVec`].
399///
400/// This struct is composed of "Sparse" and "Dense" layers. Sparse layer is
401/// literally sparse, so it can contain vacant slots in it, while dense layer
402/// doesn't. Dense layer contains real items and the items can be accessed
403/// through the sparse layer. Each dense is identified by its item's [`TypeId`].
404/// But you are encouraged to access each dense by its index, not `TypeId` for
405/// the performance.
406///
407/// We call each dense layer a column, and all columns have the same length.
408/// So it looks like a 2D matrix as shown below.
409///
410/// ```text
411/// Index  Sparse  Dense  Dense
412///                  A      B
413///   0      0 _____ .      .
414///   1      2 _   _ .      .
415///   2      x  \_/_ .      .
416///   3      1 __/   
417///
418/// , where '.' is item and 'x' is vacant slot.
419/// ```
420#[derive(Debug)]
421pub struct SparseSet<S> {
422    sparse: OptVec<usize, S>,
423    deref: Vec<usize>,
424    cols: Vec<Holder<AnyVec, RawGetter, RawGetter>>,
425    map: HashMap<TypeId, usize, S>,
426}
427
428impl<S> SparseSet<S>
429where
430    S: Default,
431{
432    /// Creates a new empty [`SparseSet`].
433    ///
434    /// # Examples
435    ///
436    /// ```
437    /// # use my_ecs::prelude::*;
438    ///
439    /// let mut cont = SparseSet::<std::hash::RandomState>::new();
440    /// ```
441    pub fn new() -> Self {
442        Self {
443            sparse: OptVec::new(),
444            deref: Vec::new(),
445            cols: Vec::new(),
446            map: HashMap::default(),
447        }
448    }
449}
450
451impl<S> ContainEntity for SparseSet<S>
452where
453    S: BuildHasher + Default + Clone + 'static,
454{
455    fn create_twin(&self) -> Box<dyn ContainEntity> {
456        // Creates new `Holder`s for the same types.
457        let cols = self
458            .cols
459            .iter()
460            .map(|col| {
461                let (fn_imm, fn_mut) = (col.get_fn_imm(), col.get_fn_mut());
462                let col = col.get().unwrap();
463                let value = AnyVec::new(*col.type_info());
464                // Safety: It's safe to create the same `Holder`. The safety
465                // must have been guaranteed by source `Holder`.
466                unsafe { Holder::new(value, fn_imm, fn_mut) }
467            })
468            .collect::<Vec<_>>();
469
470        // We can reuse mapping information.
471        let map = self.map.clone();
472
473        // Makes empty instance.
474        let this = Self {
475            sparse: OptVec::new(),
476            deref: Vec::new(),
477            cols,
478            map,
479        };
480        Box::new(this)
481    }
482
483    fn get_item_mut(&mut self, ci: usize, ri: usize) -> Option<NonNull<u8>> {
484        let key = ri;
485
486        let index = *self.sparse.get(key)?;
487        let col = self.cols.get_mut(ci)?;
488        let col = col.get_mut().unwrap();
489        col.get_raw(index)
490    }
491
492    fn len(&self) -> usize {
493        // All columns must have the same length.
494        self.cols
495            .first()
496            .map(|col| unsafe { col.get_unchecked().len() })
497            .unwrap_or_default()
498    }
499
500    fn capacity(&self) -> usize {
501        // All columns must have the same length.
502        self.cols
503            .first()
504            .map(|col| unsafe { col.get_unchecked().capacity() })
505            .unwrap_or_default()
506    }
507
508    fn reserve(&mut self, additional: usize) {
509        for col in self.cols.iter_mut() {
510            col.get_mut().unwrap().reserve(additional);
511        }
512    }
513
514    fn shrink_to_fit(&mut self) {
515        for col in self.cols.iter_mut() {
516            col.get_mut().unwrap().shrink_to_fit();
517        }
518    }
519
520    unsafe fn resize_column(&mut self, ci: usize, new_len: usize, val_ptr: NonNull<u8>) {
521        let mut col = self.cols[ci].get_mut().unwrap();
522        assert!(col.is_clone());
523        unsafe { col.resize_raw(new_len, val_ptr) };
524    }
525}
526
527impl<S> RegisterComponent for SparseSet<S>
528where
529    S: BuildHasher + Default + Clone + 'static,
530{
531    fn add_column(&mut self, tinfo: TypeInfo) -> Option<usize> {
532        let ty = tinfo.ty;
533        if self.len() > 0 || self.get_column_index(&ty).is_some() {
534            return None;
535        }
536
537        // Holder's immutable access function.
538        fn fn_imm(col: &AnyVec) -> RawGetter {
539            // Safety: Infallible.
540            let this = unsafe { NonNull::new_unchecked((col as *const _ as *const u8).cast_mut()) };
541            let len = col.len();
542            unsafe fn fn_get(this: NonNull<u8>, index: usize) -> NonNull<u8> {
543                unsafe { this.cast::<AnyVec>().as_ref().get_raw_unchecked(index) }
544            }
545            unsafe fn fn_iter(this: NonNull<u8>) -> FlatRawIter {
546                let this = unsafe { this.cast::<AnyVec>().as_ref() };
547                this.iter2()
548            }
549            // Safety: The pointer is valid.
550            let getter = unsafe { RawGetter::new(this, len, fn_get) };
551            getter.with_iter(fn_iter)
552        }
553
554        // Holder's mutable access function.
555        fn fn_mut(col: &mut AnyVec) -> RawGetter {
556            fn_imm(col)
557        }
558
559        // Adds column wrapped with Holder.
560        let value = AnyVec::new(tinfo);
561        // Safety: `fn_imm` and `fn_mut` don't return lifetime-constrained type.
562        let holder = unsafe { Holder::new(value, fn_imm, fn_mut) };
563        self.cols.push(holder);
564
565        let ci = self.cols.len() - 1;
566        self.map.insert(ty, ci);
567        Some(ci)
568    }
569
570    fn remove_column(&mut self, ci: usize) -> Option<TypeInfo> {
571        if ci >= self.num_columns() || self.cols[ci].borrow_count() != 0 {
572            return None;
573        }
574
575        let old = self.cols.remove(ci);
576
577        // Does re-mapping.
578        for i in ci..self.cols.len() {
579            let col = self.cols[i].get().unwrap();
580            let ty = col.type_id();
581            *self.map.get_mut(&ty).unwrap() = i;
582        }
583
584        // If empty, initialize self completely.
585        if self.cols.is_empty() {
586            mem::take(self);
587        }
588
589        let old = old.get().unwrap();
590        let tinfo = old.type_info();
591        Some(*tinfo)
592    }
593
594    fn get_column_index(&self, ty: &TypeId) -> Option<usize> {
595        self.map.get(ty).cloned()
596    }
597
598    fn get_column_info(&self, ci: usize) -> Option<&TypeInfo> {
599        self.cols.get(ci).map(|col| {
600            let col = col.get().unwrap();
601            col.type_info()
602        })
603    }
604
605    fn num_columns(&self) -> usize {
606        self.cols.len()
607    }
608
609    fn contains_column(&self, ty: &TypeId) -> bool {
610        self.map.contains_key(ty)
611    }
612}
613
614impl<S> BorrowComponent for SparseSet<S>
615where
616    S: BuildHasher + Default + Clone + 'static,
617{
618    fn borrow_column(&self, ci: usize) -> BorrowResult<RawGetter> {
619        #[cfg(feature = "check")]
620        let this_len = self.len();
621
622        if let Some(col) = self.cols.get(ci) {
623            let borrowed = col.borrow();
624
625            // Validates length.
626            #[cfg(feature = "check")]
627            {
628                if let Ok(borrowed) = borrowed.as_ref() {
629                    assert_eq!(
630                        this_len,
631                        borrowed.len(),
632                        "borrowed column must have the same length as entity container's"
633                    );
634                }
635            }
636
637            borrowed
638        } else {
639            Err(BorrowError::OutOfBound)
640        }
641    }
642
643    fn borrow_column_mut(&mut self, ci: usize) -> BorrowResult<RawGetter> {
644        #[cfg(feature = "check")]
645        let this_len = self.len();
646
647        if let Some(col) = self.cols.get_mut(ci) {
648            let borrowed = col.borrow_mut();
649
650            // Validates length.
651            #[cfg(feature = "check")]
652            {
653                if let Ok(borrowed) = borrowed.as_ref() {
654                    assert_eq!(
655                        this_len,
656                        borrowed.len(),
657                        "borrowed column must have the same length as entity container's"
658                    );
659                }
660            }
661
662            borrowed
663        } else {
664            Err(BorrowError::OutOfBound)
665        }
666    }
667
668    unsafe fn get_column(&self, ci: usize) -> Option<NonNull<u8>> {
669        self.cols.get(ci).map(|col| unsafe {
670            let ptr = col.get_unchecked() as *const _ as *const u8;
671            NonNull::new_unchecked(ptr.cast_mut())
672        })
673    }
674}
675
676impl<S> AddEntity for SparseSet<S>
677where
678    S: BuildHasher + Default + Clone + 'static,
679{
680    fn to_value_index(&self, ri: usize) -> Option<usize> {
681        let key = ri;
682
683        self.sparse.get(key).cloned()
684    }
685
686    fn begin_add_row(&mut self) {}
687
688    unsafe fn add_value(&mut self, ci: usize, val_ptr: NonNull<u8>) {
689        unsafe {
690            // Panics if holder has been borrowed and not returned yet.
691            let holder = self.cols.get_unchecked_mut(ci);
692            let mut col = holder.get_mut().unwrap_unchecked();
693            col.push_raw(val_ptr);
694        }
695    }
696
697    unsafe fn end_add_row(&mut self) -> usize {
698        let vi = self.deref.len();
699        let ri = self.sparse.add(vi);
700        self.deref.push(ri);
701        ri
702    }
703
704    fn value_ptr_by_value_index(&self, ci: usize, vi: usize) -> Option<NonNull<u8>> {
705        // Safety: Getting pointer is ok.
706        let col = unsafe { self.cols.get(ci)?.get_unchecked() };
707        col.get_raw(vi)
708    }
709
710    fn remove_row(&mut self, ri: usize) -> bool {
711        if let Some(vi) = self.to_value_index(ri) {
712            self.remove_row_by_value_index(vi);
713            true
714        } else {
715            false
716        }
717    }
718
719    fn remove_row_by_value_index(&mut self, vi: usize) {
720        unsafe {
721            self.begin_remove_row_by_value_index(vi);
722            for ci in 0..self.num_columns() {
723                self.drop_value_by_value_index(ci, vi);
724            }
725            self.end_remove_row_by_value_index(vi);
726        }
727    }
728
729    unsafe fn begin_remove_row_by_value_index(&mut self, vi: usize) {
730        assert!(vi < self.len());
731    }
732
733    unsafe fn remove_value_by_value_index(&mut self, ci: usize, vi: usize, buf: NonNull<u8>) {
734        unsafe {
735            let holder = self.cols.get_unchecked_mut(ci);
736            let mut col = holder.get_mut().unwrap();
737            col.swap_remove_raw(vi, buf.as_ptr());
738        }
739    }
740
741    unsafe fn drop_value_by_value_index(&mut self, ci: usize, vi: usize) {
742        let holder = unsafe { self.cols.get_unchecked_mut(ci) };
743        let mut col = holder.get_mut().unwrap();
744        col.swap_remove_drop(vi);
745    }
746
747    unsafe fn forget_value_by_value_index(&mut self, ci: usize, vi: usize) {
748        let holder = unsafe { self.cols.get_unchecked_mut(ci) };
749        let mut col = holder.get_mut().unwrap();
750        col.swap_remove_forget(vi);
751    }
752
753    unsafe fn end_remove_row_by_value_index(&mut self, vi: usize) {
754        let ri = self.deref.swap_remove(vi);
755        let _vi = self.sparse.take(ri);
756        debug_assert_eq!(_vi, Some(vi));
757        if vi < self.deref.len() {
758            let moved_key = self.deref[vi];
759            *self.sparse.get_mut(moved_key).unwrap() = vi;
760        }
761    }
762}
763
764impl<S> Default for SparseSet<S>
765where
766    S: Default,
767{
768    fn default() -> Self {
769        Self::new()
770    }
771}
772
773#[cfg(test)]
774mod tests {
775    use crate as my_ecs;
776    use crate::prelude::*;
777    use std::{hash::RandomState, sync::Arc};
778
779    #[test]
780    fn test_move_entity_to_entity_container() {
781        inner(SparseSet::<RandomState>::new());
782        inner(ChunkSparseSet::<RandomState>::new());
783
784        fn inner<T: ContainEntity>(mut cont: T) {
785            #![allow(unused)]
786
787            #[derive(Entity)]
788            struct Ea {
789                ca: Ca,
790                cb: Cb,
791            }
792            #[derive(Component)]
793            struct Ca(i32);
794            #[derive(Component)]
795            struct Cb(Arc<String>);
796
797            Ea::register_to(&mut cont);
798
799            // Tests `Entity::move_to`.
800            let b = Arc::new("0".to_owned());
801
802            let ri_0 = Ea {
803                ca: Ca(0),
804                cb: Cb(Arc::clone(&b)),
805            }
806            .move_to(&mut cont);
807            assert_eq!(Arc::strong_count(&b), 2);
808            assert_eq!(cont.len(), 1);
809
810            let ri_1 = Ea {
811                ca: Ca(1),
812                cb: Cb(Arc::clone(&b)),
813            }
814            .move_to(&mut cont);
815            assert_eq!(Arc::strong_count(&b), 3);
816            assert_eq!(cont.len(), 2);
817
818            // Correctly moved? checks it by removing.
819            cont.remove_row(ri_0);
820            assert_eq!(Arc::strong_count(&b), 2);
821            cont.remove_row(ri_1);
822            assert_eq!(Arc::strong_count(&b), 1);
823        }
824    }
825
826    #[test]
827    fn test_reserve_entity_container() {
828        fn inner<T: ContainEntity>(mut cont: T) {
829            #![allow(unused)]
830
831            #[derive(Entity)]
832            struct Ea {
833                ca: Ca,
834            }
835            #[derive(Component)]
836            struct Ca(i32);
837
838            Ea::register_to(&mut cont);
839
840            assert_eq!(cont.capacity(), 0);
841            assert_eq!(cont.len(), 0);
842
843            let reserve_size = ChunkSparseSet::<RandomState>::CHUNK_SIZE + 1;
844            cont.reserve(reserve_size);
845
846            assert!(cont.capacity() >= reserve_size);
847            assert_eq!(cont.len(), 0);
848        }
849    }
850}