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 {}