1use super::{Component, Entity, SparseSet};
41
42pub trait ComponentStorage: Send + Sync {
106 type Item: Component;
108
109 fn insert(&mut self, entity: Entity, value: Self::Item) -> Option<Self::Item>;
127
128 fn remove(&mut self, entity: Entity) -> Option<Self::Item>;
138
139 fn get(&self, entity: Entity) -> Option<&Self::Item>;
149
150 fn get_mut(&mut self, entity: Entity) -> Option<&mut Self::Item>;
160
161 fn contains(&self, entity: Entity) -> bool;
167
168 fn len(&self) -> usize;
170
171 fn is_empty(&self) -> bool;
173}
174
175impl<T: Component> ComponentStorage for SparseSet<T> {
180 type Item = T;
181
182 #[inline]
183 fn insert(&mut self, entity: Entity, value: T) -> Option<T> {
184 SparseSet::insert(self, entity, value)
185 }
186
187 #[inline]
188 fn remove(&mut self, entity: Entity) -> Option<T> {
189 SparseSet::remove(self, entity)
190 }
191
192 #[inline]
193 fn get(&self, entity: Entity) -> Option<&T> {
194 SparseSet::get(self, entity)
195 }
196
197 #[inline]
198 fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
199 SparseSet::get_mut(self, entity)
200 }
201
202 #[inline]
203 fn contains(&self, entity: Entity) -> bool {
204 SparseSet::contains(self, entity)
205 }
206
207 #[inline]
208 fn len(&self) -> usize {
209 SparseSet::len(self)
210 }
211
212 #[inline]
213 fn is_empty(&self) -> bool {
214 SparseSet::is_empty(self)
215 }
216}
217
218pub trait AnyComponentStorage: Send + Sync {
252 fn contains_entity(&self, entity: Entity) -> bool;
254
255 fn remove_entity(&mut self, entity: Entity) -> bool;
259
260 fn storage_len(&self) -> usize;
262
263 fn storage_is_empty(&self) -> bool;
265
266 fn clear(&mut self);
268
269 fn component_type_name(&self) -> &'static str;
271}
272
273impl<T: Component> AnyComponentStorage for SparseSet<T> {
274 #[inline]
275 fn contains_entity(&self, entity: Entity) -> bool {
276 self.contains(entity)
277 }
278
279 #[inline]
280 fn remove_entity(&mut self, entity: Entity) -> bool {
281 self.remove(entity).is_some()
282 }
283
284 #[inline]
285 fn storage_len(&self) -> usize {
286 self.len()
287 }
288
289 #[inline]
290 fn storage_is_empty(&self) -> bool {
291 self.is_empty()
292 }
293
294 #[inline]
295 fn clear(&mut self) {
296 SparseSet::clear(self)
297 }
298
299 #[inline]
300 fn component_type_name(&self) -> &'static str {
301 std::any::type_name::<T>()
302 }
303}
304
305#[cfg(test)]
310mod tests {
311 use super::*;
312
313 #[derive(Debug, Clone, Copy, PartialEq)]
315 struct Position {
316 x: f32,
317 y: f32,
318 }
319 impl Component for Position {}
320
321 #[derive(Debug, Clone, Copy, PartialEq)]
322 struct Velocity {
323 x: f32,
324 y: f32,
325 }
326 impl Component for Velocity {}
327
328 #[derive(Debug, Clone, PartialEq)]
329 struct Name(String);
330 impl Component for Name {}
331
332 #[derive(Debug, Clone, Copy, PartialEq)]
334 struct Player;
335 impl Component for Player {}
336
337 mod component_storage_trait {
342 use super::*;
343
344 #[test]
345 fn test_sparse_set_implements_component_storage() {
346 fn assert_component_storage<S: ComponentStorage>() {}
348 assert_component_storage::<SparseSet<Position>>();
349 assert_component_storage::<SparseSet<Velocity>>();
350 assert_component_storage::<SparseSet<Name>>();
351 assert_component_storage::<SparseSet<Player>>();
352 }
353
354 #[test]
355 fn test_component_storage_is_send_sync() {
356 fn assert_send_sync<T: Send + Sync>() {}
357 assert_send_sync::<SparseSet<Position>>();
358 assert_send_sync::<SparseSet<Name>>();
359 }
360
361 #[test]
362 fn test_insert_via_trait() {
363 let mut storage: SparseSet<Position> = SparseSet::new();
364 let entity = Entity::new(0, 1);
365
366 let old = ComponentStorage::insert(&mut storage, entity, Position { x: 1.0, y: 2.0 });
367
368 assert_eq!(old, None);
369 assert!(storage.contains(entity));
370 }
371
372 #[test]
373 fn test_insert_replace_via_trait() {
374 let mut storage: SparseSet<Position> = SparseSet::new();
375 let entity = Entity::new(0, 1);
376
377 ComponentStorage::insert(&mut storage, entity, Position { x: 1.0, y: 2.0 });
378 let old = ComponentStorage::insert(&mut storage, entity, Position { x: 3.0, y: 4.0 });
379
380 assert_eq!(old, Some(Position { x: 1.0, y: 2.0 }));
381 assert_eq!(
382 ComponentStorage::get(&storage, entity),
383 Some(&Position { x: 3.0, y: 4.0 })
384 );
385 }
386
387 #[test]
388 fn test_remove_via_trait() {
389 let mut storage: SparseSet<Position> = SparseSet::new();
390 let entity = Entity::new(0, 1);
391
392 storage.insert(entity, Position { x: 1.0, y: 2.0 });
393 let removed = ComponentStorage::remove(&mut storage, entity);
394
395 assert_eq!(removed, Some(Position { x: 1.0, y: 2.0 }));
396 assert!(!storage.contains(entity));
397 }
398
399 #[test]
400 fn test_remove_nonexistent_via_trait() {
401 let mut storage: SparseSet<Position> = SparseSet::new();
402 let entity = Entity::new(0, 1);
403
404 let removed = ComponentStorage::remove(&mut storage, entity);
405 assert_eq!(removed, None);
406 }
407
408 #[test]
409 fn test_get_via_trait() {
410 let mut storage: SparseSet<Position> = SparseSet::new();
411 let entity = Entity::new(0, 1);
412
413 storage.insert(entity, Position { x: 5.0, y: 10.0 });
414 let pos = ComponentStorage::get(&storage, entity);
415
416 assert_eq!(pos, Some(&Position { x: 5.0, y: 10.0 }));
417 }
418
419 #[test]
420 fn test_get_nonexistent_via_trait() {
421 let storage: SparseSet<Position> = SparseSet::new();
422 let entity = Entity::new(0, 1);
423
424 assert_eq!(ComponentStorage::get(&storage, entity), None);
425 }
426
427 #[test]
428 fn test_get_mut_via_trait() {
429 let mut storage: SparseSet<Position> = SparseSet::new();
430 let entity = Entity::new(0, 1);
431
432 storage.insert(entity, Position { x: 1.0, y: 2.0 });
433
434 if let Some(pos) = ComponentStorage::get_mut(&mut storage, entity) {
435 pos.x = 100.0;
436 pos.y = 200.0;
437 }
438
439 assert_eq!(storage.get(entity), Some(&Position { x: 100.0, y: 200.0 }));
440 }
441
442 #[test]
443 fn test_contains_via_trait() {
444 let mut storage: SparseSet<Position> = SparseSet::new();
445 let e1 = Entity::new(0, 1);
446 let e2 = Entity::new(1, 1);
447
448 storage.insert(e1, Position { x: 0.0, y: 0.0 });
449
450 assert!(ComponentStorage::contains(&storage, e1));
451 assert!(!ComponentStorage::contains(&storage, e2));
452 }
453
454 #[test]
455 fn test_len_via_trait() {
456 let mut storage: SparseSet<Position> = SparseSet::new();
457
458 assert_eq!(ComponentStorage::len(&storage), 0);
459
460 storage.insert(Entity::new(0, 1), Position { x: 0.0, y: 0.0 });
461 assert_eq!(ComponentStorage::len(&storage), 1);
462
463 storage.insert(Entity::new(1, 1), Position { x: 1.0, y: 1.0 });
464 assert_eq!(ComponentStorage::len(&storage), 2);
465 }
466
467 #[test]
468 fn test_is_empty_via_trait() {
469 let mut storage: SparseSet<Position> = SparseSet::new();
470
471 assert!(ComponentStorage::is_empty(&storage));
472
473 storage.insert(Entity::new(0, 1), Position { x: 0.0, y: 0.0 });
474 assert!(!ComponentStorage::is_empty(&storage));
475 }
476
477 #[test]
478 fn test_generic_function_with_component_storage() {
479 #[allow(dead_code)]
481 fn count_matching<S>(storage: &S, predicate: impl Fn(&Position) -> bool) -> usize
482 where
483 S: ComponentStorage<Item = Position> + AsRef<SparseSet<Position>>,
484 {
485 storage
486 .as_ref()
487 .iter()
488 .filter(|(_, pos)| predicate(pos))
489 .count()
490 }
491
492 let mut storage: SparseSet<Position> = SparseSet::new();
495 storage.insert(Entity::new(0, 1), Position { x: 1.0, y: 2.0 });
496 storage.insert(Entity::new(1, 1), Position { x: 3.0, y: 4.0 });
497
498 assert_eq!(ComponentStorage::len(&storage), 2);
499 }
500 }
501
502 mod any_component_storage {
507 use super::*;
508
509 #[test]
510 fn test_sparse_set_implements_any_component_storage() {
511 fn assert_any_storage<S: AnyComponentStorage>() {}
512 assert_any_storage::<SparseSet<Position>>();
513 assert_any_storage::<SparseSet<Name>>();
514 }
515
516 #[test]
517 fn test_any_storage_is_object_safe() {
518 let _storage: Box<dyn AnyComponentStorage> = Box::new(SparseSet::<Position>::new());
520 }
521
522 #[test]
523 fn test_contains_entity_via_any() {
524 let storage: Box<dyn AnyComponentStorage> = Box::new(SparseSet::<Position>::new());
525
526 let entity = Entity::new(0, 1);
527
528 assert!(!storage.contains_entity(entity));
529
530 }
533
534 #[test]
535 fn test_storage_len_via_any() {
536 let mut storage = SparseSet::<Position>::new();
537 storage.insert(Entity::new(0, 1), Position { x: 0.0, y: 0.0 });
538 storage.insert(Entity::new(1, 1), Position { x: 1.0, y: 1.0 });
539
540 let any_storage: &dyn AnyComponentStorage = &storage;
541
542 assert_eq!(any_storage.storage_len(), 2);
543 assert!(!any_storage.storage_is_empty());
544 }
545
546 #[test]
547 fn test_remove_entity_via_any() {
548 let mut storage = SparseSet::<Position>::new();
549 let entity = Entity::new(0, 1);
550
551 storage.insert(entity, Position { x: 1.0, y: 2.0 });
552
553 let any_storage: &mut dyn AnyComponentStorage = &mut storage;
554
555 assert!(any_storage.contains_entity(entity));
556 let removed = any_storage.remove_entity(entity);
557
558 assert!(removed);
559 assert!(!any_storage.contains_entity(entity));
560 }
561
562 #[test]
563 fn test_remove_nonexistent_via_any() {
564 let mut storage = SparseSet::<Position>::new();
565 let entity = Entity::new(0, 1);
566
567 let any_storage: &mut dyn AnyComponentStorage = &mut storage;
568 let removed = any_storage.remove_entity(entity);
569
570 assert!(!removed);
571 }
572
573 #[test]
574 fn test_clear_via_any() {
575 let mut storage = SparseSet::<Position>::new();
576 storage.insert(Entity::new(0, 1), Position { x: 0.0, y: 0.0 });
577 storage.insert(Entity::new(1, 1), Position { x: 1.0, y: 1.0 });
578
579 let any_storage: &mut dyn AnyComponentStorage = &mut storage;
580 any_storage.clear();
581
582 assert!(any_storage.storage_is_empty());
583 assert_eq!(any_storage.storage_len(), 0);
584 }
585
586 #[test]
587 fn test_component_type_name_via_any() {
588 let storage = SparseSet::<Position>::new();
589 let any_storage: &dyn AnyComponentStorage = &storage;
590
591 let name = any_storage.component_type_name();
592 assert!(name.contains("Position"));
593 }
594
595 #[test]
596 fn test_multiple_storages_as_any() {
597 let mut positions = SparseSet::<Position>::new();
598 let mut velocities = SparseSet::<Velocity>::new();
599
600 positions.insert(Entity::new(0, 1), Position { x: 1.0, y: 2.0 });
601 velocities.insert(Entity::new(0, 1), Velocity { x: 3.0, y: 4.0 });
602
603 let storages: Vec<&dyn AnyComponentStorage> = vec![&positions, &velocities];
604
605 assert_eq!(storages[0].storage_len(), 1);
606 assert_eq!(storages[1].storage_len(), 1);
607
608 assert!(storages[0].component_type_name().contains("Position"));
609 assert!(storages[1].component_type_name().contains("Velocity"));
610 }
611
612 #[test]
613 fn test_any_storage_is_empty() {
614 let storage: Box<dyn AnyComponentStorage> = Box::new(SparseSet::<Position>::new());
615 assert!(storage.storage_is_empty());
616 }
617 }
618
619 mod integration {
624 use super::*;
625
626 #[test]
627 fn test_component_storage_workflow() {
628 let mut storage: SparseSet<Position> = SparseSet::new();
629
630 let e1 = Entity::new(0, 1);
632 let e2 = Entity::new(1, 1);
633 let e3 = Entity::new(2, 1);
634
635 ComponentStorage::insert(&mut storage, e1, Position { x: 0.0, y: 0.0 });
637 ComponentStorage::insert(&mut storage, e2, Position { x: 10.0, y: 20.0 });
638 ComponentStorage::insert(&mut storage, e3, Position { x: 100.0, y: 200.0 });
639
640 assert_eq!(ComponentStorage::len(&storage), 3);
641
642 if let Some(pos) = ComponentStorage::get_mut(&mut storage, e2) {
644 pos.x += 5.0;
645 pos.y += 5.0;
646 }
647
648 assert_eq!(
650 ComponentStorage::get(&storage, e2),
651 Some(&Position { x: 15.0, y: 25.0 })
652 );
653
654 let removed = ComponentStorage::remove(&mut storage, e1);
656 assert_eq!(removed, Some(Position { x: 0.0, y: 0.0 }));
657 assert_eq!(ComponentStorage::len(&storage), 2);
658
659 assert!(ComponentStorage::contains(&storage, e2));
661 assert!(ComponentStorage::contains(&storage, e3));
662 }
663
664 #[test]
665 fn test_zero_sized_component_storage() {
666 let mut storage: SparseSet<Player> = SparseSet::new();
667
668 let e1 = Entity::new(0, 1);
669 let e2 = Entity::new(1, 1);
670
671 ComponentStorage::insert(&mut storage, e1, Player);
672 ComponentStorage::insert(&mut storage, e2, Player);
673
674 assert_eq!(ComponentStorage::len(&storage), 2);
675 assert!(ComponentStorage::contains(&storage, e1));
676 assert!(ComponentStorage::contains(&storage, e2));
677
678 assert_eq!(ComponentStorage::get(&storage, e1), Some(&Player));
680 }
681
682 #[test]
683 fn test_string_component_storage() {
684 let mut storage: SparseSet<Name> = SparseSet::new();
685
686 let entity = Entity::new(0, 1);
687 ComponentStorage::insert(&mut storage, entity, Name("Player".to_string()));
688
689 assert_eq!(
690 ComponentStorage::get(&storage, entity),
691 Some(&Name("Player".to_string()))
692 );
693
694 let old = ComponentStorage::insert(&mut storage, entity, Name("Enemy".to_string()));
696 assert_eq!(old, Some(Name("Player".to_string())));
697 }
698 }
699}