goud_engine/ecs/components/hierarchy.rs
1//! Hierarchy components for parent-child entity relationships.
2//!
3//! This module provides components for building entity hierarchies, enabling
4//! parent-child relationships between entities. This is essential for:
5//!
6//! - Scene graphs where child transforms are relative to parent transforms
7//! - UI layouts where child widgets are positioned within parent containers
8//! - Game object grouping where destroying a parent also destroys children
9//!
10//! # Components
11//!
12//! - [`Parent`]: Points to the parent entity (stored on child entities)
13//! - [`Children`]: Lists all child entities (stored on parent entities)
14//! - [`Name`]: Human-readable name for debugging and editor integration
15//!
16//! # Design Philosophy
17//!
18//! The hierarchy system uses a bidirectional pointer approach:
19//! - Children point up to their parent via [`Parent`]
20//! - Parents point down to their children via [`Children`]
21//!
22//! This redundancy enables efficient traversal in both directions and
23//! matches the design of major engines like Bevy, Unity, and Godot.
24//!
25//! # Usage
26//!
27//! ```
28//! use goud_engine::ecs::{World, Entity};
29//! use goud_engine::ecs::components::{Parent, Children, Name};
30//!
31//! let mut world = World::new();
32//!
33//! // Create parent entity
34//! let parent = world.spawn_empty();
35//! world.insert(parent, Name::new("Player"));
36//! world.insert(parent, Children::new());
37//!
38//! // Create child entity
39//! let child = world.spawn_empty();
40//! world.insert(child, Name::new("Weapon"));
41//! world.insert(child, Parent::new(parent));
42//!
43//! // Update parent's children list (normally done by a hierarchy system)
44//! if let Some(children) = world.get_mut::<Children>(parent) {
45//! children.push(child);
46//! }
47//! ```
48//!
49//! # FFI Safety
50//!
51//! All hierarchy components are `#[repr(C)]` where applicable for FFI
52//! compatibility. String data uses Rust's `String` type internally but
53//! provides FFI-safe accessor methods.
54//!
55//! # Consistency
56//!
57//! **Important**: The hierarchy must be kept consistent. When adding a child:
58//! 1. Add `Parent` component to the child pointing to parent
59//! 2. Add/update `Children` component on parent to include child
60//!
61//! When removing a child:
62//! 1. Remove `Parent` component from child (or update to new parent)
63//! 2. Remove child from parent's `Children` list
64//!
65//! A hierarchy maintenance system should be used to ensure consistency.
66
67use crate::ecs::entity::Entity;
68use crate::ecs::Component;
69use std::fmt;
70
71// =============================================================================
72// Parent Component
73// =============================================================================
74
75/// Component indicating the parent entity of this entity.
76///
77/// When an entity has a `Parent` component, its transform (if any) is
78/// considered to be in the parent's local coordinate space. The hierarchy
79/// propagation system will compute the global transform by combining
80/// the parent's global transform with this entity's local transform.
81///
82/// # Memory Layout
83///
84/// ```text
85/// Parent (8 bytes total):
86/// ┌────────────────┬────────────────┐
87/// │ index (u32) │ generation(u32)│ <- Entity
88/// └────────────────┴────────────────┘
89/// ```
90///
91/// # Example
92///
93/// ```
94/// use goud_engine::ecs::Entity;
95/// use goud_engine::ecs::components::Parent;
96///
97/// let parent_entity = Entity::new(0, 1);
98/// let parent_component = Parent::new(parent_entity);
99///
100/// assert_eq!(parent_component.get(), parent_entity);
101/// ```
102#[repr(C)]
103#[derive(Clone, Copy, PartialEq, Eq, Hash)]
104pub struct Parent {
105 /// The parent entity.
106 entity: Entity,
107}
108
109impl Parent {
110 /// Creates a new Parent component pointing to the given entity.
111 ///
112 /// # Arguments
113 ///
114 /// * `parent` - The entity that should be this entity's parent
115 ///
116 /// # Example
117 ///
118 /// ```
119 /// use goud_engine::ecs::Entity;
120 /// use goud_engine::ecs::components::Parent;
121 ///
122 /// let parent_entity = Entity::new(42, 1);
123 /// let parent = Parent::new(parent_entity);
124 /// ```
125 #[inline]
126 pub const fn new(parent: Entity) -> Self {
127 Self { entity: parent }
128 }
129
130 /// Returns the parent entity.
131 ///
132 /// # Example
133 ///
134 /// ```
135 /// use goud_engine::ecs::Entity;
136 /// use goud_engine::ecs::components::Parent;
137 ///
138 /// let parent_entity = Entity::new(10, 2);
139 /// let parent = Parent::new(parent_entity);
140 ///
141 /// assert_eq!(parent.get(), parent_entity);
142 /// ```
143 #[inline]
144 pub const fn get(&self) -> Entity {
145 self.entity
146 }
147
148 /// Sets the parent entity.
149 ///
150 /// This allows changing the parent without removing and re-adding the component.
151 ///
152 /// # Arguments
153 ///
154 /// * `parent` - The new parent entity
155 ///
156 /// # Example
157 ///
158 /// ```
159 /// use goud_engine::ecs::Entity;
160 /// use goud_engine::ecs::components::Parent;
161 ///
162 /// let mut parent = Parent::new(Entity::new(0, 1));
163 /// parent.set(Entity::new(5, 1));
164 ///
165 /// assert_eq!(parent.get(), Entity::new(5, 1));
166 /// ```
167 #[inline]
168 pub fn set(&mut self, parent: Entity) {
169 self.entity = parent;
170 }
171}
172
173impl fmt::Debug for Parent {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 write!(f, "Parent({:?})", self.entity)
176 }
177}
178
179impl fmt::Display for Parent {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 write!(f, "Parent({})", self.entity)
182 }
183}
184
185impl Default for Parent {
186 /// Returns a Parent with PLACEHOLDER entity.
187 ///
188 /// This is primarily for initialization purposes. A valid parent should
189 /// be set before the entity is used in a hierarchy.
190 #[inline]
191 fn default() -> Self {
192 Self {
193 entity: Entity::PLACEHOLDER,
194 }
195 }
196}
197
198impl From<Entity> for Parent {
199 #[inline]
200 fn from(entity: Entity) -> Self {
201 Self::new(entity)
202 }
203}
204
205impl From<Parent> for Entity {
206 #[inline]
207 fn from(parent: Parent) -> Self {
208 parent.entity
209 }
210}
211
212// Implement Component trait
213impl Component for Parent {}
214
215// =============================================================================
216// Children Component
217// =============================================================================
218
219/// Component containing a list of child entities.
220///
221/// This component stores references to all immediate children of an entity.
222/// The order of children is preserved and can be significant for rendering
223/// order or other order-dependent operations.
224///
225/// # Capacity and Performance
226///
227/// Internally uses a `Vec<Entity>`, so:
228/// - Adding children is O(1) amortized
229/// - Removing children is O(n) where n is the number of children
230/// - Iteration is cache-friendly
231///
232/// For entities with many children, consider using `with_capacity` to
233/// pre-allocate memory.
234///
235/// # Example
236///
237/// ```
238/// use goud_engine::ecs::Entity;
239/// use goud_engine::ecs::components::Children;
240///
241/// let mut children = Children::new();
242///
243/// let child1 = Entity::new(1, 1);
244/// let child2 = Entity::new(2, 1);
245///
246/// children.push(child1);
247/// children.push(child2);
248///
249/// assert_eq!(children.len(), 2);
250/// assert!(children.contains(child1));
251/// ```
252#[derive(Clone, PartialEq, Eq)]
253pub struct Children {
254 /// The list of child entities in order.
255 children: Vec<Entity>,
256}
257
258impl Children {
259 /// Creates an empty Children component.
260 ///
261 /// # Example
262 ///
263 /// ```
264 /// use goud_engine::ecs::components::Children;
265 ///
266 /// let children = Children::new();
267 /// assert!(children.is_empty());
268 /// ```
269 #[inline]
270 pub fn new() -> Self {
271 Self {
272 children: Vec::new(),
273 }
274 }
275
276 /// Creates a Children component with pre-allocated capacity.
277 ///
278 /// Use this when you know approximately how many children the entity will have.
279 ///
280 /// # Arguments
281 ///
282 /// * `capacity` - The number of children to pre-allocate space for
283 ///
284 /// # Example
285 ///
286 /// ```
287 /// use goud_engine::ecs::components::Children;
288 ///
289 /// let children = Children::with_capacity(100);
290 /// assert!(children.is_empty()); // No children yet
291 /// ```
292 #[inline]
293 pub fn with_capacity(capacity: usize) -> Self {
294 Self {
295 children: Vec::with_capacity(capacity),
296 }
297 }
298
299 /// Creates a Children component from a slice of entities.
300 ///
301 /// # Arguments
302 ///
303 /// * `children` - Slice of child entities
304 ///
305 /// # Example
306 ///
307 /// ```
308 /// use goud_engine::ecs::Entity;
309 /// use goud_engine::ecs::components::Children;
310 ///
311 /// let entities = vec![Entity::new(1, 1), Entity::new(2, 1)];
312 /// let children = Children::from_slice(&entities);
313 ///
314 /// assert_eq!(children.len(), 2);
315 /// ```
316 #[inline]
317 pub fn from_slice(children: &[Entity]) -> Self {
318 Self {
319 children: children.to_vec(),
320 }
321 }
322
323 /// Returns the number of children.
324 ///
325 /// # Example
326 ///
327 /// ```
328 /// use goud_engine::ecs::Entity;
329 /// use goud_engine::ecs::components::Children;
330 ///
331 /// let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
332 /// assert_eq!(children.len(), 2);
333 /// ```
334 #[inline]
335 pub fn len(&self) -> usize {
336 self.children.len()
337 }
338
339 /// Returns `true` if there are no children.
340 ///
341 /// # Example
342 ///
343 /// ```
344 /// use goud_engine::ecs::components::Children;
345 ///
346 /// let children = Children::new();
347 /// assert!(children.is_empty());
348 /// ```
349 #[inline]
350 pub fn is_empty(&self) -> bool {
351 self.children.is_empty()
352 }
353
354 /// Adds a child entity to the end of the children list.
355 ///
356 /// # Arguments
357 ///
358 /// * `child` - The child entity to add
359 ///
360 /// # Example
361 ///
362 /// ```
363 /// use goud_engine::ecs::Entity;
364 /// use goud_engine::ecs::components::Children;
365 ///
366 /// let mut children = Children::new();
367 /// children.push(Entity::new(1, 1));
368 /// assert_eq!(children.len(), 1);
369 /// ```
370 #[inline]
371 pub fn push(&mut self, child: Entity) {
372 self.children.push(child);
373 }
374
375 /// Inserts a child entity at a specific index.
376 ///
377 /// # Arguments
378 ///
379 /// * `index` - The index to insert at
380 /// * `child` - The child entity to insert
381 ///
382 /// # Panics
383 ///
384 /// Panics if `index > len`.
385 ///
386 /// # Example
387 ///
388 /// ```
389 /// use goud_engine::ecs::Entity;
390 /// use goud_engine::ecs::components::Children;
391 ///
392 /// let mut children = Children::new();
393 /// children.push(Entity::new(1, 1));
394 /// children.push(Entity::new(3, 1));
395 /// children.insert(1, Entity::new(2, 1)); // Insert at index 1
396 ///
397 /// assert_eq!(children.get(1), Some(Entity::new(2, 1)));
398 /// ```
399 #[inline]
400 pub fn insert(&mut self, index: usize, child: Entity) {
401 self.children.insert(index, child);
402 }
403
404 /// Removes and returns the child at the specified index.
405 ///
406 /// # Arguments
407 ///
408 /// * `index` - The index of the child to remove
409 ///
410 /// # Returns
411 ///
412 /// The removed child entity.
413 ///
414 /// # Panics
415 ///
416 /// Panics if `index >= len`.
417 ///
418 /// # Example
419 ///
420 /// ```
421 /// use goud_engine::ecs::Entity;
422 /// use goud_engine::ecs::components::Children;
423 ///
424 /// let mut children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
425 /// let removed = children.remove(0);
426 ///
427 /// assert_eq!(removed, Entity::new(1, 1));
428 /// assert_eq!(children.len(), 1);
429 /// ```
430 #[inline]
431 pub fn remove(&mut self, index: usize) -> Entity {
432 self.children.remove(index)
433 }
434
435 /// Removes a child entity if it exists, preserving order.
436 ///
437 /// # Arguments
438 ///
439 /// * `child` - The child entity to remove
440 ///
441 /// # Returns
442 ///
443 /// `true` if the child was found and removed, `false` otherwise.
444 ///
445 /// # Performance
446 ///
447 /// This is O(n) as it must search for the child and shift elements.
448 ///
449 /// # Example
450 ///
451 /// ```
452 /// use goud_engine::ecs::Entity;
453 /// use goud_engine::ecs::components::Children;
454 ///
455 /// let mut children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
456 ///
457 /// assert!(children.remove_child(Entity::new(1, 1)));
458 /// assert!(!children.remove_child(Entity::new(1, 1))); // Already removed
459 /// ```
460 pub fn remove_child(&mut self, child: Entity) -> bool {
461 if let Some(index) = self.children.iter().position(|&e| e == child) {
462 self.children.remove(index);
463 true
464 } else {
465 false
466 }
467 }
468
469 /// Removes a child entity using swap-remove (faster but doesn't preserve order).
470 ///
471 /// # Arguments
472 ///
473 /// * `child` - The child entity to remove
474 ///
475 /// # Returns
476 ///
477 /// `true` if the child was found and removed, `false` otherwise.
478 ///
479 /// # Performance
480 ///
481 /// This is O(n) for the search but O(1) for the actual removal.
482 /// Use this when child order doesn't matter.
483 ///
484 /// # Example
485 ///
486 /// ```
487 /// use goud_engine::ecs::Entity;
488 /// use goud_engine::ecs::components::Children;
489 ///
490 /// let mut children = Children::from_slice(&[
491 /// Entity::new(1, 1),
492 /// Entity::new(2, 1),
493 /// Entity::new(3, 1),
494 /// ]);
495 ///
496 /// children.swap_remove_child(Entity::new(1, 1));
497 /// // Order may have changed, but length is now 2
498 /// assert_eq!(children.len(), 2);
499 /// ```
500 pub fn swap_remove_child(&mut self, child: Entity) -> bool {
501 if let Some(index) = self.children.iter().position(|&e| e == child) {
502 self.children.swap_remove(index);
503 true
504 } else {
505 false
506 }
507 }
508
509 /// Returns `true` if the given entity is a child.
510 ///
511 /// # Arguments
512 ///
513 /// * `child` - The entity to check
514 ///
515 /// # Example
516 ///
517 /// ```
518 /// use goud_engine::ecs::Entity;
519 /// use goud_engine::ecs::components::Children;
520 ///
521 /// let children = Children::from_slice(&[Entity::new(1, 1)]);
522 ///
523 /// assert!(children.contains(Entity::new(1, 1)));
524 /// assert!(!children.contains(Entity::new(2, 1)));
525 /// ```
526 #[inline]
527 pub fn contains(&self, child: Entity) -> bool {
528 self.children.contains(&child)
529 }
530
531 /// Returns the child at the given index, if any.
532 ///
533 /// # Arguments
534 ///
535 /// * `index` - The index of the child to get
536 ///
537 /// # Returns
538 ///
539 /// `Some(entity)` if the index is valid, `None` otherwise.
540 ///
541 /// # Example
542 ///
543 /// ```
544 /// use goud_engine::ecs::Entity;
545 /// use goud_engine::ecs::components::Children;
546 ///
547 /// let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
548 ///
549 /// assert_eq!(children.get(0), Some(Entity::new(1, 1)));
550 /// assert_eq!(children.get(10), None);
551 /// ```
552 #[inline]
553 pub fn get(&self, index: usize) -> Option<Entity> {
554 self.children.get(index).copied()
555 }
556
557 /// Returns the first child, if any.
558 ///
559 /// # Example
560 ///
561 /// ```
562 /// use goud_engine::ecs::Entity;
563 /// use goud_engine::ecs::components::Children;
564 ///
565 /// let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
566 /// assert_eq!(children.first(), Some(Entity::new(1, 1)));
567 ///
568 /// let empty = Children::new();
569 /// assert_eq!(empty.first(), None);
570 /// ```
571 #[inline]
572 pub fn first(&self) -> Option<Entity> {
573 self.children.first().copied()
574 }
575
576 /// Returns the last child, if any.
577 ///
578 /// # Example
579 ///
580 /// ```
581 /// use goud_engine::ecs::Entity;
582 /// use goud_engine::ecs::components::Children;
583 ///
584 /// let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
585 /// assert_eq!(children.last(), Some(Entity::new(2, 1)));
586 /// ```
587 #[inline]
588 pub fn last(&self) -> Option<Entity> {
589 self.children.last().copied()
590 }
591
592 /// Returns an iterator over the children.
593 ///
594 /// # Example
595 ///
596 /// ```
597 /// use goud_engine::ecs::Entity;
598 /// use goud_engine::ecs::components::Children;
599 ///
600 /// let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
601 ///
602 /// for child in children.iter() {
603 /// println!("Child: {:?}", child);
604 /// }
605 /// ```
606 #[inline]
607 pub fn iter(&self) -> impl Iterator<Item = &Entity> {
608 self.children.iter()
609 }
610
611 /// Returns the index of a child entity, if it exists.
612 ///
613 /// # Arguments
614 ///
615 /// * `child` - The entity to find
616 ///
617 /// # Returns
618 ///
619 /// `Some(index)` if found, `None` otherwise.
620 ///
621 /// # Example
622 ///
623 /// ```
624 /// use goud_engine::ecs::Entity;
625 /// use goud_engine::ecs::components::Children;
626 ///
627 /// let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
628 ///
629 /// assert_eq!(children.index_of(Entity::new(2, 1)), Some(1));
630 /// assert_eq!(children.index_of(Entity::new(99, 1)), None);
631 /// ```
632 #[inline]
633 pub fn index_of(&self, child: Entity) -> Option<usize> {
634 self.children.iter().position(|&e| e == child)
635 }
636
637 /// Removes all children.
638 ///
639 /// # Example
640 ///
641 /// ```
642 /// use goud_engine::ecs::Entity;
643 /// use goud_engine::ecs::components::Children;
644 ///
645 /// let mut children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
646 /// children.clear();
647 ///
648 /// assert!(children.is_empty());
649 /// ```
650 #[inline]
651 pub fn clear(&mut self) {
652 self.children.clear();
653 }
654
655 /// Returns the children as a slice.
656 ///
657 /// # Example
658 ///
659 /// ```
660 /// use goud_engine::ecs::Entity;
661 /// use goud_engine::ecs::components::Children;
662 ///
663 /// let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
664 /// let slice = children.as_slice();
665 ///
666 /// assert_eq!(slice.len(), 2);
667 /// ```
668 #[inline]
669 pub fn as_slice(&self) -> &[Entity] {
670 &self.children
671 }
672
673 /// Retains only the children that satisfy the predicate.
674 ///
675 /// # Arguments
676 ///
677 /// * `f` - The predicate function
678 ///
679 /// # Example
680 ///
681 /// ```
682 /// use goud_engine::ecs::Entity;
683 /// use goud_engine::ecs::components::Children;
684 ///
685 /// let mut children = Children::from_slice(&[
686 /// Entity::new(1, 1),
687 /// Entity::new(2, 1),
688 /// Entity::new(3, 1),
689 /// ]);
690 ///
691 /// // Keep only entities with even indices
692 /// children.retain(|e| e.index() % 2 == 0);
693 ///
694 /// assert_eq!(children.len(), 1);
695 /// assert!(children.contains(Entity::new(2, 1)));
696 /// ```
697 #[inline]
698 pub fn retain<F>(&mut self, f: F)
699 where
700 F: FnMut(&Entity) -> bool,
701 {
702 self.children.retain(f);
703 }
704
705 /// Sorts children by their entity index.
706 ///
707 /// This can be useful for deterministic ordering.
708 ///
709 /// # Example
710 ///
711 /// ```
712 /// use goud_engine::ecs::Entity;
713 /// use goud_engine::ecs::components::Children;
714 ///
715 /// let mut children = Children::from_slice(&[
716 /// Entity::new(3, 1),
717 /// Entity::new(1, 1),
718 /// Entity::new(2, 1),
719 /// ]);
720 ///
721 /// children.sort_by_index();
722 ///
723 /// assert_eq!(children.get(0), Some(Entity::new(1, 1)));
724 /// assert_eq!(children.get(1), Some(Entity::new(2, 1)));
725 /// assert_eq!(children.get(2), Some(Entity::new(3, 1)));
726 /// ```
727 pub fn sort_by_index(&mut self) {
728 self.children.sort_by_key(|e| e.index());
729 }
730
731 /// Sorts children using a custom comparison function.
732 ///
733 /// # Example
734 ///
735 /// ```
736 /// use goud_engine::ecs::Entity;
737 /// use goud_engine::ecs::components::Children;
738 ///
739 /// let mut children = Children::from_slice(&[
740 /// Entity::new(1, 1),
741 /// Entity::new(2, 1),
742 /// Entity::new(3, 1),
743 /// ]);
744 ///
745 /// // Sort in reverse order
746 /// children.sort_by(|a, b| b.index().cmp(&a.index()));
747 ///
748 /// assert_eq!(children.get(0), Some(Entity::new(3, 1)));
749 /// ```
750 pub fn sort_by<F>(&mut self, compare: F)
751 where
752 F: FnMut(&Entity, &Entity) -> std::cmp::Ordering,
753 {
754 self.children.sort_by(compare);
755 }
756}
757
758impl Default for Children {
759 #[inline]
760 fn default() -> Self {
761 Self::new()
762 }
763}
764
765impl fmt::Debug for Children {
766 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
767 f.debug_struct("Children")
768 .field("count", &self.children.len())
769 .field("children", &self.children)
770 .finish()
771 }
772}
773
774impl fmt::Display for Children {
775 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
776 write!(f, "Children({})", self.children.len())
777 }
778}
779
780impl<'a> IntoIterator for &'a Children {
781 type Item = &'a Entity;
782 type IntoIter = std::slice::Iter<'a, Entity>;
783
784 #[inline]
785 fn into_iter(self) -> Self::IntoIter {
786 self.children.iter()
787 }
788}
789
790impl IntoIterator for Children {
791 type Item = Entity;
792 type IntoIter = std::vec::IntoIter<Entity>;
793
794 #[inline]
795 fn into_iter(self) -> Self::IntoIter {
796 self.children.into_iter()
797 }
798}
799
800impl From<Vec<Entity>> for Children {
801 #[inline]
802 fn from(children: Vec<Entity>) -> Self {
803 Self { children }
804 }
805}
806
807impl From<&[Entity]> for Children {
808 #[inline]
809 fn from(children: &[Entity]) -> Self {
810 Self::from_slice(children)
811 }
812}
813
814impl From<Children> for Vec<Entity> {
815 #[inline]
816 fn from(children: Children) -> Self {
817 children.children
818 }
819}
820
821// Implement Component trait
822impl Component for Children {}
823
824// =============================================================================
825// Name Component
826// =============================================================================
827
828/// Component providing a human-readable name for an entity.
829///
830/// Names are useful for:
831/// - Debugging and logging
832/// - Editor integration and scene hierarchies
833/// - Scripting references (find entity by name)
834/// - UI display
835///
836/// # Performance
837///
838/// Names use Rust's `String` type internally. For performance-critical code,
839/// consider using entity IDs directly rather than string lookups.
840///
841/// # Example
842///
843/// ```
844/// use goud_engine::ecs::components::Name;
845///
846/// let name = Name::new("Player");
847/// assert_eq!(name.as_str(), "Player");
848///
849/// let mut name = Name::new("Enemy");
850/// name.set("Boss");
851/// assert_eq!(name.as_str(), "Boss");
852/// ```
853#[derive(Clone, PartialEq, Eq, Hash)]
854pub struct Name {
855 /// The name string.
856 name: String,
857}
858
859impl Name {
860 /// Creates a new Name component with the given string.
861 ///
862 /// # Arguments
863 ///
864 /// * `name` - The name string (anything that can be converted to String)
865 ///
866 /// # Example
867 ///
868 /// ```
869 /// use goud_engine::ecs::components::Name;
870 ///
871 /// let name = Name::new("Player");
872 /// let name2 = Name::new(String::from("Enemy"));
873 /// ```
874 #[inline]
875 pub fn new(name: impl Into<String>) -> Self {
876 Self { name: name.into() }
877 }
878
879 /// Returns the name as a string slice.
880 ///
881 /// # Example
882 ///
883 /// ```
884 /// use goud_engine::ecs::components::Name;
885 ///
886 /// let name = Name::new("Player");
887 /// assert_eq!(name.as_str(), "Player");
888 /// ```
889 #[inline]
890 pub fn as_str(&self) -> &str {
891 &self.name
892 }
893
894 /// Sets a new name.
895 ///
896 /// # Arguments
897 ///
898 /// * `name` - The new name string
899 ///
900 /// # Example
901 ///
902 /// ```
903 /// use goud_engine::ecs::components::Name;
904 ///
905 /// let mut name = Name::new("Player");
906 /// name.set("Player_renamed");
907 /// assert_eq!(name.as_str(), "Player_renamed");
908 /// ```
909 #[inline]
910 pub fn set(&mut self, name: impl Into<String>) {
911 self.name = name.into();
912 }
913
914 /// Returns the length of the name in bytes.
915 ///
916 /// # Example
917 ///
918 /// ```
919 /// use goud_engine::ecs::components::Name;
920 ///
921 /// let name = Name::new("Test");
922 /// assert_eq!(name.len(), 4);
923 /// ```
924 #[inline]
925 pub fn len(&self) -> usize {
926 self.name.len()
927 }
928
929 /// Returns `true` if the name is empty.
930 ///
931 /// # Example
932 ///
933 /// ```
934 /// use goud_engine::ecs::components::Name;
935 ///
936 /// let name = Name::new("");
937 /// assert!(name.is_empty());
938 ///
939 /// let name2 = Name::new("Player");
940 /// assert!(!name2.is_empty());
941 /// ```
942 #[inline]
943 pub fn is_empty(&self) -> bool {
944 self.name.is_empty()
945 }
946
947 /// Consumes the Name and returns the inner String.
948 ///
949 /// # Example
950 ///
951 /// ```
952 /// use goud_engine::ecs::components::Name;
953 ///
954 /// let name = Name::new("Player");
955 /// let string: String = name.into_string();
956 /// assert_eq!(string, "Player");
957 /// ```
958 #[inline]
959 pub fn into_string(self) -> String {
960 self.name
961 }
962
963 /// Returns `true` if the name contains the given pattern.
964 ///
965 /// # Example
966 ///
967 /// ```
968 /// use goud_engine::ecs::components::Name;
969 ///
970 /// let name = Name::new("Player_01");
971 /// assert!(name.contains("Player"));
972 /// assert!(name.contains("01"));
973 /// assert!(!name.contains("Enemy"));
974 /// ```
975 #[inline]
976 pub fn contains(&self, pattern: &str) -> bool {
977 self.name.contains(pattern)
978 }
979
980 /// Returns `true` if the name starts with the given prefix.
981 ///
982 /// # Example
983 ///
984 /// ```
985 /// use goud_engine::ecs::components::Name;
986 ///
987 /// let name = Name::new("Player_01");
988 /// assert!(name.starts_with("Player"));
989 /// assert!(!name.starts_with("Enemy"));
990 /// ```
991 #[inline]
992 pub fn starts_with(&self, prefix: &str) -> bool {
993 self.name.starts_with(prefix)
994 }
995
996 /// Returns `true` if the name ends with the given suffix.
997 ///
998 /// # Example
999 ///
1000 /// ```
1001 /// use goud_engine::ecs::components::Name;
1002 ///
1003 /// let name = Name::new("Player_01");
1004 /// assert!(name.ends_with("01"));
1005 /// assert!(!name.ends_with("Player"));
1006 /// ```
1007 #[inline]
1008 pub fn ends_with(&self, suffix: &str) -> bool {
1009 self.name.ends_with(suffix)
1010 }
1011}
1012
1013impl Default for Name {
1014 /// Returns a Name with an empty string.
1015 #[inline]
1016 fn default() -> Self {
1017 Self {
1018 name: String::new(),
1019 }
1020 }
1021}
1022
1023impl fmt::Debug for Name {
1024 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1025 write!(f, "Name({:?})", self.name)
1026 }
1027}
1028
1029impl fmt::Display for Name {
1030 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1031 write!(f, "{}", self.name)
1032 }
1033}
1034
1035impl From<&str> for Name {
1036 #[inline]
1037 fn from(s: &str) -> Self {
1038 Self::new(s)
1039 }
1040}
1041
1042impl From<String> for Name {
1043 #[inline]
1044 fn from(s: String) -> Self {
1045 Self { name: s }
1046 }
1047}
1048
1049impl From<Name> for String {
1050 #[inline]
1051 fn from(name: Name) -> Self {
1052 name.name
1053 }
1054}
1055
1056impl AsRef<str> for Name {
1057 #[inline]
1058 fn as_ref(&self) -> &str {
1059 &self.name
1060 }
1061}
1062
1063impl std::borrow::Borrow<str> for Name {
1064 #[inline]
1065 fn borrow(&self) -> &str {
1066 &self.name
1067 }
1068}
1069
1070impl PartialEq<str> for Name {
1071 #[inline]
1072 fn eq(&self, other: &str) -> bool {
1073 self.name == other
1074 }
1075}
1076
1077impl PartialEq<&str> for Name {
1078 #[inline]
1079 fn eq(&self, other: &&str) -> bool {
1080 self.name == *other
1081 }
1082}
1083
1084impl PartialEq<String> for Name {
1085 #[inline]
1086 fn eq(&self, other: &String) -> bool {
1087 &self.name == other
1088 }
1089}
1090
1091// Implement Component trait
1092impl Component for Name {}
1093
1094// =============================================================================
1095// Unit Tests
1096// =============================================================================
1097
1098#[cfg(test)]
1099mod tests {
1100 use super::*;
1101
1102 // =========================================================================
1103 // Parent Tests
1104 // =========================================================================
1105
1106 mod parent_tests {
1107 use super::*;
1108
1109 #[test]
1110 fn test_parent_new() {
1111 let entity = Entity::new(42, 1);
1112 let parent = Parent::new(entity);
1113 assert_eq!(parent.get(), entity);
1114 }
1115
1116 #[test]
1117 fn test_parent_get() {
1118 let entity = Entity::new(10, 2);
1119 let parent = Parent::new(entity);
1120 assert_eq!(parent.get().index(), 10);
1121 assert_eq!(parent.get().generation(), 2);
1122 }
1123
1124 #[test]
1125 fn test_parent_set() {
1126 let mut parent = Parent::new(Entity::new(0, 1));
1127 parent.set(Entity::new(5, 3));
1128 assert_eq!(parent.get(), Entity::new(5, 3));
1129 }
1130
1131 #[test]
1132 fn test_parent_default() {
1133 let parent = Parent::default();
1134 assert!(parent.get().is_placeholder());
1135 }
1136
1137 #[test]
1138 fn test_parent_from_entity() {
1139 let entity = Entity::new(7, 2);
1140 let parent: Parent = entity.into();
1141 assert_eq!(parent.get(), entity);
1142 }
1143
1144 #[test]
1145 fn test_entity_from_parent() {
1146 let parent = Parent::new(Entity::new(7, 2));
1147 let entity: Entity = parent.into();
1148 assert_eq!(entity, Entity::new(7, 2));
1149 }
1150
1151 #[test]
1152 fn test_parent_clone_copy() {
1153 let parent = Parent::new(Entity::new(1, 1));
1154 let cloned = parent.clone();
1155 let copied = parent;
1156 assert_eq!(parent, cloned);
1157 assert_eq!(parent, copied);
1158 }
1159
1160 #[test]
1161 fn test_parent_eq() {
1162 let p1 = Parent::new(Entity::new(1, 1));
1163 let p2 = Parent::new(Entity::new(1, 1));
1164 let p3 = Parent::new(Entity::new(2, 1));
1165 assert_eq!(p1, p2);
1166 assert_ne!(p1, p3);
1167 }
1168
1169 #[test]
1170 fn test_parent_hash() {
1171 use std::collections::HashSet;
1172 let mut set = HashSet::new();
1173 set.insert(Parent::new(Entity::new(1, 1)));
1174 assert!(set.contains(&Parent::new(Entity::new(1, 1))));
1175 assert!(!set.contains(&Parent::new(Entity::new(2, 1))));
1176 }
1177
1178 #[test]
1179 fn test_parent_debug() {
1180 let parent = Parent::new(Entity::new(42, 3));
1181 let debug = format!("{:?}", parent);
1182 assert!(debug.contains("Parent"));
1183 assert!(debug.contains("42"));
1184 }
1185
1186 #[test]
1187 fn test_parent_display() {
1188 let parent = Parent::new(Entity::new(42, 3));
1189 let display = format!("{}", parent);
1190 assert!(display.contains("Parent"));
1191 }
1192
1193 #[test]
1194 fn test_parent_is_component() {
1195 fn assert_component<T: Component>() {}
1196 assert_component::<Parent>();
1197 }
1198
1199 #[test]
1200 fn test_parent_is_send_sync() {
1201 fn assert_send_sync<T: Send + Sync>() {}
1202 assert_send_sync::<Parent>();
1203 }
1204
1205 #[test]
1206 fn test_parent_size() {
1207 // Parent wraps Entity, so should be same size
1208 assert_eq!(std::mem::size_of::<Parent>(), std::mem::size_of::<Entity>());
1209 assert_eq!(std::mem::size_of::<Parent>(), 8);
1210 }
1211 }
1212
1213 // =========================================================================
1214 // Children Tests
1215 // =========================================================================
1216
1217 mod children_tests {
1218 use super::*;
1219
1220 #[test]
1221 fn test_children_new() {
1222 let children = Children::new();
1223 assert!(children.is_empty());
1224 assert_eq!(children.len(), 0);
1225 }
1226
1227 #[test]
1228 fn test_children_with_capacity() {
1229 let children = Children::with_capacity(100);
1230 assert!(children.is_empty());
1231 }
1232
1233 #[test]
1234 fn test_children_from_slice() {
1235 let entities = vec![Entity::new(1, 1), Entity::new(2, 1)];
1236 let children = Children::from_slice(&entities);
1237 assert_eq!(children.len(), 2);
1238 }
1239
1240 #[test]
1241 fn test_children_push() {
1242 let mut children = Children::new();
1243 children.push(Entity::new(1, 1));
1244 children.push(Entity::new(2, 1));
1245 assert_eq!(children.len(), 2);
1246 assert_eq!(children.get(0), Some(Entity::new(1, 1)));
1247 assert_eq!(children.get(1), Some(Entity::new(2, 1)));
1248 }
1249
1250 #[test]
1251 fn test_children_insert() {
1252 let mut children = Children::new();
1253 children.push(Entity::new(1, 1));
1254 children.push(Entity::new(3, 1));
1255 children.insert(1, Entity::new(2, 1));
1256 assert_eq!(children.get(1), Some(Entity::new(2, 1)));
1257 assert_eq!(children.len(), 3);
1258 }
1259
1260 #[test]
1261 fn test_children_remove() {
1262 let mut children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1263 let removed = children.remove(0);
1264 assert_eq!(removed, Entity::new(1, 1));
1265 assert_eq!(children.len(), 1);
1266 }
1267
1268 #[test]
1269 fn test_children_remove_child() {
1270 let mut children =
1271 Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1), Entity::new(3, 1)]);
1272
1273 assert!(children.remove_child(Entity::new(2, 1)));
1274 assert_eq!(children.len(), 2);
1275 assert!(!children.contains(Entity::new(2, 1)));
1276
1277 // Order preserved
1278 assert_eq!(children.get(0), Some(Entity::new(1, 1)));
1279 assert_eq!(children.get(1), Some(Entity::new(3, 1)));
1280
1281 // Already removed
1282 assert!(!children.remove_child(Entity::new(2, 1)));
1283 }
1284
1285 #[test]
1286 fn test_children_swap_remove_child() {
1287 let mut children =
1288 Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1), Entity::new(3, 1)]);
1289
1290 assert!(children.swap_remove_child(Entity::new(1, 1)));
1291 assert_eq!(children.len(), 2);
1292 assert!(!children.contains(Entity::new(1, 1)));
1293
1294 // Order NOT preserved (last element moved to removed position)
1295 assert!(children.contains(Entity::new(2, 1)));
1296 assert!(children.contains(Entity::new(3, 1)));
1297 }
1298
1299 #[test]
1300 fn test_children_contains() {
1301 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1302 assert!(children.contains(Entity::new(1, 1)));
1303 assert!(children.contains(Entity::new(2, 1)));
1304 assert!(!children.contains(Entity::new(3, 1)));
1305 }
1306
1307 #[test]
1308 fn test_children_get() {
1309 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1310 assert_eq!(children.get(0), Some(Entity::new(1, 1)));
1311 assert_eq!(children.get(1), Some(Entity::new(2, 1)));
1312 assert_eq!(children.get(2), None);
1313 }
1314
1315 #[test]
1316 fn test_children_first_last() {
1317 let children =
1318 Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1), Entity::new(3, 1)]);
1319 assert_eq!(children.first(), Some(Entity::new(1, 1)));
1320 assert_eq!(children.last(), Some(Entity::new(3, 1)));
1321
1322 let empty = Children::new();
1323 assert_eq!(empty.first(), None);
1324 assert_eq!(empty.last(), None);
1325 }
1326
1327 #[test]
1328 fn test_children_iter() {
1329 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1330 let collected: Vec<_> = children.iter().copied().collect();
1331 assert_eq!(collected, vec![Entity::new(1, 1), Entity::new(2, 1)]);
1332 }
1333
1334 #[test]
1335 fn test_children_index_of() {
1336 let children =
1337 Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1), Entity::new(3, 1)]);
1338 assert_eq!(children.index_of(Entity::new(1, 1)), Some(0));
1339 assert_eq!(children.index_of(Entity::new(2, 1)), Some(1));
1340 assert_eq!(children.index_of(Entity::new(3, 1)), Some(2));
1341 assert_eq!(children.index_of(Entity::new(99, 1)), None);
1342 }
1343
1344 #[test]
1345 fn test_children_clear() {
1346 let mut children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1347 children.clear();
1348 assert!(children.is_empty());
1349 }
1350
1351 #[test]
1352 fn test_children_as_slice() {
1353 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1354 let slice = children.as_slice();
1355 assert_eq!(slice.len(), 2);
1356 assert_eq!(slice[0], Entity::new(1, 1));
1357 }
1358
1359 #[test]
1360 fn test_children_retain() {
1361 let mut children = Children::from_slice(&[
1362 Entity::new(1, 1),
1363 Entity::new(2, 1),
1364 Entity::new(3, 1),
1365 Entity::new(4, 1),
1366 ]);
1367
1368 children.retain(|e| e.index() % 2 == 0);
1369
1370 assert_eq!(children.len(), 2);
1371 assert!(children.contains(Entity::new(2, 1)));
1372 assert!(children.contains(Entity::new(4, 1)));
1373 }
1374
1375 #[test]
1376 fn test_children_sort_by_index() {
1377 let mut children =
1378 Children::from_slice(&[Entity::new(3, 1), Entity::new(1, 1), Entity::new(2, 1)]);
1379
1380 children.sort_by_index();
1381
1382 assert_eq!(children.get(0), Some(Entity::new(1, 1)));
1383 assert_eq!(children.get(1), Some(Entity::new(2, 1)));
1384 assert_eq!(children.get(2), Some(Entity::new(3, 1)));
1385 }
1386
1387 #[test]
1388 fn test_children_sort_by() {
1389 let mut children =
1390 Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1), Entity::new(3, 1)]);
1391
1392 // Reverse sort
1393 children.sort_by(|a, b| b.index().cmp(&a.index()));
1394
1395 assert_eq!(children.get(0), Some(Entity::new(3, 1)));
1396 assert_eq!(children.get(1), Some(Entity::new(2, 1)));
1397 assert_eq!(children.get(2), Some(Entity::new(1, 1)));
1398 }
1399
1400 #[test]
1401 fn test_children_default() {
1402 let children: Children = Default::default();
1403 assert!(children.is_empty());
1404 }
1405
1406 #[test]
1407 fn test_children_debug() {
1408 let children = Children::from_slice(&[Entity::new(1, 1)]);
1409 let debug = format!("{:?}", children);
1410 assert!(debug.contains("Children"));
1411 assert!(debug.contains("count"));
1412 }
1413
1414 #[test]
1415 fn test_children_display() {
1416 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1417 let display = format!("{}", children);
1418 assert!(display.contains("Children(2)"));
1419 }
1420
1421 #[test]
1422 fn test_children_into_iter_ref() {
1423 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1424 let collected: Vec<_> = (&children).into_iter().copied().collect();
1425 assert_eq!(collected, vec![Entity::new(1, 1), Entity::new(2, 1)]);
1426 }
1427
1428 #[test]
1429 fn test_children_into_iter_owned() {
1430 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1431 let collected: Vec<_> = children.into_iter().collect();
1432 assert_eq!(collected, vec![Entity::new(1, 1), Entity::new(2, 1)]);
1433 }
1434
1435 #[test]
1436 fn test_children_from_vec() {
1437 let vec = vec![Entity::new(1, 1), Entity::new(2, 1)];
1438 let children: Children = vec.into();
1439 assert_eq!(children.len(), 2);
1440 }
1441
1442 #[test]
1443 fn test_children_from_slice_trait() {
1444 let slice = &[Entity::new(1, 1), Entity::new(2, 1)][..];
1445 let children: Children = slice.into();
1446 assert_eq!(children.len(), 2);
1447 }
1448
1449 #[test]
1450 fn test_vec_from_children() {
1451 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1452 let vec: Vec<Entity> = children.into();
1453 assert_eq!(vec.len(), 2);
1454 }
1455
1456 #[test]
1457 fn test_children_is_component() {
1458 fn assert_component<T: Component>() {}
1459 assert_component::<Children>();
1460 }
1461
1462 #[test]
1463 fn test_children_is_send_sync() {
1464 fn assert_send_sync<T: Send + Sync>() {}
1465 assert_send_sync::<Children>();
1466 }
1467
1468 #[test]
1469 fn test_children_clone() {
1470 let children = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1471 let cloned = children.clone();
1472 assert_eq!(children, cloned);
1473 }
1474
1475 #[test]
1476 fn test_children_eq() {
1477 let c1 = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1478 let c2 = Children::from_slice(&[Entity::new(1, 1), Entity::new(2, 1)]);
1479 let c3 = Children::from_slice(&[Entity::new(2, 1), Entity::new(1, 1)]); // Different order
1480
1481 assert_eq!(c1, c2);
1482 assert_ne!(c1, c3); // Order matters
1483 }
1484
1485 #[test]
1486 fn test_children_many() {
1487 let mut children = Children::new();
1488 for i in 0..1000 {
1489 children.push(Entity::new(i, 1));
1490 }
1491 assert_eq!(children.len(), 1000);
1492
1493 for i in 0..1000 {
1494 assert!(children.contains(Entity::new(i, 1)));
1495 }
1496 }
1497 }
1498
1499 // =========================================================================
1500 // Name Tests
1501 // =========================================================================
1502
1503 mod name_tests {
1504 use super::*;
1505
1506 #[test]
1507 fn test_name_new() {
1508 let name = Name::new("Player");
1509 assert_eq!(name.as_str(), "Player");
1510 }
1511
1512 #[test]
1513 fn test_name_new_string() {
1514 let name = Name::new(String::from("Enemy"));
1515 assert_eq!(name.as_str(), "Enemy");
1516 }
1517
1518 #[test]
1519 fn test_name_as_str() {
1520 let name = Name::new("Test");
1521 assert_eq!(name.as_str(), "Test");
1522 }
1523
1524 #[test]
1525 fn test_name_set() {
1526 let mut name = Name::new("Old");
1527 name.set("New");
1528 assert_eq!(name.as_str(), "New");
1529 }
1530
1531 #[test]
1532 fn test_name_set_string() {
1533 let mut name = Name::new("Old");
1534 name.set(String::from("New"));
1535 assert_eq!(name.as_str(), "New");
1536 }
1537
1538 #[test]
1539 fn test_name_len() {
1540 let name = Name::new("Test");
1541 assert_eq!(name.len(), 4);
1542
1543 let empty = Name::new("");
1544 assert_eq!(empty.len(), 0);
1545 }
1546
1547 #[test]
1548 fn test_name_is_empty() {
1549 let empty = Name::new("");
1550 assert!(empty.is_empty());
1551
1552 let non_empty = Name::new("Player");
1553 assert!(!non_empty.is_empty());
1554 }
1555
1556 #[test]
1557 fn test_name_into_string() {
1558 let name = Name::new("Player");
1559 let s: String = name.into_string();
1560 assert_eq!(s, "Player");
1561 }
1562
1563 #[test]
1564 fn test_name_contains() {
1565 let name = Name::new("Player_01");
1566 assert!(name.contains("Player"));
1567 assert!(name.contains("01"));
1568 assert!(name.contains("_"));
1569 assert!(!name.contains("Enemy"));
1570 }
1571
1572 #[test]
1573 fn test_name_starts_with() {
1574 let name = Name::new("Player_01");
1575 assert!(name.starts_with("Player"));
1576 assert!(name.starts_with("Play"));
1577 assert!(!name.starts_with("Enemy"));
1578 }
1579
1580 #[test]
1581 fn test_name_ends_with() {
1582 let name = Name::new("Player_01");
1583 assert!(name.ends_with("01"));
1584 assert!(name.ends_with("_01"));
1585 assert!(!name.ends_with("Player"));
1586 }
1587
1588 #[test]
1589 fn test_name_default() {
1590 let name: Name = Default::default();
1591 assert!(name.is_empty());
1592 assert_eq!(name.as_str(), "");
1593 }
1594
1595 #[test]
1596 fn test_name_debug() {
1597 let name = Name::new("Test");
1598 let debug = format!("{:?}", name);
1599 assert!(debug.contains("Name"));
1600 assert!(debug.contains("Test"));
1601 }
1602
1603 #[test]
1604 fn test_name_display() {
1605 let name = Name::new("Player");
1606 let display = format!("{}", name);
1607 assert_eq!(display, "Player");
1608 }
1609
1610 #[test]
1611 fn test_name_from_str() {
1612 let name: Name = "Test".into();
1613 assert_eq!(name.as_str(), "Test");
1614 }
1615
1616 #[test]
1617 fn test_name_from_string() {
1618 let name: Name = String::from("Test").into();
1619 assert_eq!(name.as_str(), "Test");
1620 }
1621
1622 #[test]
1623 fn test_string_from_name() {
1624 let name = Name::new("Test");
1625 let s: String = name.into();
1626 assert_eq!(s, "Test");
1627 }
1628
1629 #[test]
1630 fn test_name_as_ref() {
1631 let name = Name::new("Test");
1632 let s: &str = name.as_ref();
1633 assert_eq!(s, "Test");
1634 }
1635
1636 #[test]
1637 fn test_name_borrow() {
1638 use std::borrow::Borrow;
1639 let name = Name::new("Test");
1640 let s: &str = name.borrow();
1641 assert_eq!(s, "Test");
1642 }
1643
1644 #[test]
1645 fn test_name_eq_str() {
1646 let name = Name::new("Test");
1647 assert!(name == *"Test");
1648 assert!(name == "Test");
1649 assert!(name != *"Other");
1650 }
1651
1652 #[test]
1653 fn test_name_eq_string() {
1654 let name = Name::new("Test");
1655 assert!(name == String::from("Test"));
1656 assert!(name != String::from("Other"));
1657 }
1658
1659 #[test]
1660 fn test_name_clone() {
1661 let name = Name::new("Test");
1662 let cloned = name.clone();
1663 assert_eq!(name, cloned);
1664 }
1665
1666 #[test]
1667 fn test_name_eq() {
1668 let n1 = Name::new("Test");
1669 let n2 = Name::new("Test");
1670 let n3 = Name::new("Other");
1671
1672 assert_eq!(n1, n2);
1673 assert_ne!(n1, n3);
1674 }
1675
1676 #[test]
1677 fn test_name_hash() {
1678 use std::collections::HashSet;
1679 let mut set = HashSet::new();
1680 set.insert(Name::new("Player"));
1681 assert!(set.contains(&Name::new("Player")));
1682 assert!(!set.contains(&Name::new("Enemy")));
1683 }
1684
1685 #[test]
1686 fn test_name_is_component() {
1687 fn assert_component<T: Component>() {}
1688 assert_component::<Name>();
1689 }
1690
1691 #[test]
1692 fn test_name_is_send_sync() {
1693 fn assert_send_sync<T: Send + Sync>() {}
1694 assert_send_sync::<Name>();
1695 }
1696
1697 #[test]
1698 fn test_name_unicode() {
1699 let name = Name::new("玩家");
1700 assert_eq!(name.as_str(), "玩家");
1701 assert_eq!(name.len(), 6); // 2 characters, 3 bytes each in UTF-8
1702 }
1703
1704 #[test]
1705 fn test_name_emoji() {
1706 let name = Name::new("Player 🎮");
1707 assert!(name.contains("🎮"));
1708 }
1709 }
1710
1711 // =========================================================================
1712 // Integration Tests
1713 // =========================================================================
1714
1715 mod integration_tests {
1716 use super::*;
1717
1718 #[test]
1719 fn test_hierarchy_components_work_together() {
1720 // Simulate a simple hierarchy
1721 let parent_entity = Entity::new(0, 1);
1722 let child1 = Entity::new(1, 1);
1723 let child2 = Entity::new(2, 1);
1724
1725 // Parent with children
1726 let children = Children::from_slice(&[child1, child2]);
1727 assert_eq!(children.len(), 2);
1728
1729 // Children with parent
1730 let parent1 = Parent::new(parent_entity);
1731 let parent2 = Parent::new(parent_entity);
1732 assert_eq!(parent1.get(), parent_entity);
1733 assert_eq!(parent2.get(), parent_entity);
1734
1735 // Names for debugging
1736 let parent_name = Name::new("Root");
1737 let child1_name = Name::new("Child_A");
1738 let child2_name = Name::new("Child_B");
1739
1740 assert_eq!(parent_name.as_str(), "Root");
1741 assert!(child1_name.starts_with("Child"));
1742 assert!(child2_name.starts_with("Child"));
1743 }
1744
1745 #[test]
1746 fn test_hierarchy_mutation() {
1747 let parent_entity = Entity::new(0, 1);
1748 let child1 = Entity::new(1, 1);
1749 let child2 = Entity::new(2, 1);
1750 let new_parent = Entity::new(3, 1);
1751
1752 // Start with one child
1753 let mut children = Children::new();
1754 children.push(child1);
1755
1756 // Child has parent
1757 let mut parent_comp = Parent::new(parent_entity);
1758
1759 // Add another child
1760 children.push(child2);
1761 assert_eq!(children.len(), 2);
1762
1763 // Reparent the child
1764 parent_comp.set(new_parent);
1765 assert_eq!(parent_comp.get(), new_parent);
1766
1767 // Remove from old parent's children
1768 children.remove_child(child1);
1769 assert_eq!(children.len(), 1);
1770 assert!(!children.contains(child1));
1771 }
1772
1773 #[test]
1774 fn test_components_are_distinct() {
1775 // Verify these are distinct component types
1776 use crate::ecs::ComponentId;
1777
1778 let parent_id = ComponentId::of::<Parent>();
1779 let children_id = ComponentId::of::<Children>();
1780 let name_id = ComponentId::of::<Name>();
1781
1782 assert_ne!(parent_id, children_id);
1783 assert_ne!(parent_id, name_id);
1784 assert_ne!(children_id, name_id);
1785 }
1786 }
1787}