1use 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#[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 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 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 unsafe { Holder::new(value, fn_imm, fn_mut) }
85 })
86 .collect::<Vec<_>>();
87
88 let map = self.map.clone();
90
91 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 self.cols
113 .first()
114 .map(|col| unsafe { col.get_unchecked().len() })
115 .unwrap_or_default()
116 }
117
118 fn capacity(&self) -> usize {
119 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 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 fn fn_imm(col: &ChunkAnyVec) -> RawGetter {
158 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 let getter = unsafe { RawGetter::new(this, len, fn_get) };
169 getter.with_iter(fn_iter)
170 }
171
172 fn fn_mut(col: &mut ChunkAnyVec) -> RawGetter {
174 fn_imm(col)
175 }
176
177 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 };
186 let value = ChunkAnyVec::new(tinfo, chunk_len);
187 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 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 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 #[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 #[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 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 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#[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 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 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 unsafe { Holder::new(value, fn_imm, fn_mut) }
467 })
468 .collect::<Vec<_>>();
469
470 let map = self.map.clone();
472
473 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 self.cols
495 .first()
496 .map(|col| unsafe { col.get_unchecked().len() })
497 .unwrap_or_default()
498 }
499
500 fn capacity(&self) -> usize {
501 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 fn fn_imm(col: &AnyVec) -> RawGetter {
539 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 let getter = unsafe { RawGetter::new(this, len, fn_get) };
551 getter.with_iter(fn_iter)
552 }
553
554 fn fn_mut(col: &mut AnyVec) -> RawGetter {
556 fn_imm(col)
557 }
558
559 let value = AnyVec::new(tinfo);
561 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 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 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 #[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 #[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 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 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 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 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}