Skip to main content

goud_engine/ecs/components/hierarchy/
name.rs

1//! [`Name`] component for human-readable entity identification.
2
3use crate::ecs::Component;
4use std::fmt;
5
6// =============================================================================
7// Name Component
8// =============================================================================
9
10/// Component providing a human-readable name for an entity.
11///
12/// Names are useful for:
13/// - Debugging and logging
14/// - Editor integration and scene hierarchies
15/// - Scripting references (find entity by name)
16/// - UI display
17///
18/// # Performance
19///
20/// Names use Rust's `String` type internally. For performance-critical code,
21/// consider using entity IDs directly rather than string lookups.
22///
23/// # Example
24///
25/// ```
26/// use goud_engine::ecs::components::Name;
27///
28/// let name = Name::new("Player");
29/// assert_eq!(name.as_str(), "Player");
30///
31/// let mut name = Name::new("Enemy");
32/// name.set("Boss");
33/// assert_eq!(name.as_str(), "Boss");
34/// ```
35#[derive(Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
36pub struct Name {
37    /// The name string.
38    name: String,
39}
40
41impl Name {
42    /// Creates a new Name component with the given string.
43    ///
44    /// # Arguments
45    ///
46    /// * `name` - The name string (anything that can be converted to String)
47    ///
48    /// # Example
49    ///
50    /// ```
51    /// use goud_engine::ecs::components::Name;
52    ///
53    /// let name = Name::new("Player");
54    /// let name2 = Name::new(String::from("Enemy"));
55    /// ```
56    #[inline]
57    pub fn new(name: impl Into<String>) -> Self {
58        Self { name: name.into() }
59    }
60
61    /// Returns the name as a string slice.
62    ///
63    /// # Example
64    ///
65    /// ```
66    /// use goud_engine::ecs::components::Name;
67    ///
68    /// let name = Name::new("Player");
69    /// assert_eq!(name.as_str(), "Player");
70    /// ```
71    #[inline]
72    pub fn as_str(&self) -> &str {
73        &self.name
74    }
75
76    /// Sets a new name.
77    ///
78    /// # Arguments
79    ///
80    /// * `name` - The new name string
81    ///
82    /// # Example
83    ///
84    /// ```
85    /// use goud_engine::ecs::components::Name;
86    ///
87    /// let mut name = Name::new("Player");
88    /// name.set("Player_renamed");
89    /// assert_eq!(name.as_str(), "Player_renamed");
90    /// ```
91    #[inline]
92    pub fn set(&mut self, name: impl Into<String>) {
93        self.name = name.into();
94    }
95
96    /// Returns the length of the name in bytes.
97    ///
98    /// # Example
99    ///
100    /// ```
101    /// use goud_engine::ecs::components::Name;
102    ///
103    /// let name = Name::new("Test");
104    /// assert_eq!(name.len(), 4);
105    /// ```
106    #[inline]
107    pub fn len(&self) -> usize {
108        self.name.len()
109    }
110
111    /// Returns `true` if the name is empty.
112    ///
113    /// # Example
114    ///
115    /// ```
116    /// use goud_engine::ecs::components::Name;
117    ///
118    /// let name = Name::new("");
119    /// assert!(name.is_empty());
120    ///
121    /// let name2 = Name::new("Player");
122    /// assert!(!name2.is_empty());
123    /// ```
124    #[inline]
125    pub fn is_empty(&self) -> bool {
126        self.name.is_empty()
127    }
128
129    /// Consumes the Name and returns the inner String.
130    ///
131    /// # Example
132    ///
133    /// ```
134    /// use goud_engine::ecs::components::Name;
135    ///
136    /// let name = Name::new("Player");
137    /// let string: String = name.into_string();
138    /// assert_eq!(string, "Player");
139    /// ```
140    #[inline]
141    pub fn into_string(self) -> String {
142        self.name
143    }
144
145    /// Returns `true` if the name contains the given pattern.
146    ///
147    /// # Example
148    ///
149    /// ```
150    /// use goud_engine::ecs::components::Name;
151    ///
152    /// let name = Name::new("Player_01");
153    /// assert!(name.contains("Player"));
154    /// assert!(name.contains("01"));
155    /// assert!(!name.contains("Enemy"));
156    /// ```
157    #[inline]
158    pub fn contains(&self, pattern: &str) -> bool {
159        self.name.contains(pattern)
160    }
161
162    /// Returns `true` if the name starts with the given prefix.
163    ///
164    /// # Example
165    ///
166    /// ```
167    /// use goud_engine::ecs::components::Name;
168    ///
169    /// let name = Name::new("Player_01");
170    /// assert!(name.starts_with("Player"));
171    /// assert!(!name.starts_with("Enemy"));
172    /// ```
173    #[inline]
174    pub fn starts_with(&self, prefix: &str) -> bool {
175        self.name.starts_with(prefix)
176    }
177
178    /// Returns `true` if the name ends with the given suffix.
179    ///
180    /// # Example
181    ///
182    /// ```
183    /// use goud_engine::ecs::components::Name;
184    ///
185    /// let name = Name::new("Player_01");
186    /// assert!(name.ends_with("01"));
187    /// assert!(!name.ends_with("Player"));
188    /// ```
189    #[inline]
190    pub fn ends_with(&self, suffix: &str) -> bool {
191        self.name.ends_with(suffix)
192    }
193}
194
195impl Default for Name {
196    /// Returns a Name with an empty string.
197    #[inline]
198    fn default() -> Self {
199        Self {
200            name: String::new(),
201        }
202    }
203}
204
205impl fmt::Debug for Name {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        write!(f, "Name({:?})", self.name)
208    }
209}
210
211impl fmt::Display for Name {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        write!(f, "{}", self.name)
214    }
215}
216
217impl From<&str> for Name {
218    #[inline]
219    fn from(s: &str) -> Self {
220        Self::new(s)
221    }
222}
223
224impl From<String> for Name {
225    #[inline]
226    fn from(s: String) -> Self {
227        Self { name: s }
228    }
229}
230
231impl From<Name> for String {
232    #[inline]
233    fn from(name: Name) -> Self {
234        name.name
235    }
236}
237
238impl AsRef<str> for Name {
239    #[inline]
240    fn as_ref(&self) -> &str {
241        &self.name
242    }
243}
244
245impl std::borrow::Borrow<str> for Name {
246    #[inline]
247    fn borrow(&self) -> &str {
248        &self.name
249    }
250}
251
252impl PartialEq<str> for Name {
253    #[inline]
254    fn eq(&self, other: &str) -> bool {
255        self.name == other
256    }
257}
258
259impl PartialEq<&str> for Name {
260    #[inline]
261    fn eq(&self, other: &&str) -> bool {
262        self.name == *other
263    }
264}
265
266impl PartialEq<String> for Name {
267    #[inline]
268    fn eq(&self, other: &String) -> bool {
269        &self.name == other
270    }
271}
272
273// Implement Component trait
274impl Component for Name {}