1use crate::{component::Component, entity::Entity, query::QueryData};
4
5use alloc::{
6 borrow::{Cow, ToOwned},
7 string::String,
8};
9use bevy_platform::hash::FixedHasher;
10use core::{
11 hash::{BuildHasher, Hash, Hasher},
12 ops::Deref,
13};
14
15#[cfg(feature = "serialize")]
16use {
17 alloc::string::ToString,
18 serde::{
19 de::{Error, Visitor},
20 Deserialize, Deserializer, Serialize, Serializer,
21 },
22};
23
24#[cfg(feature = "bevy_reflect")]
25use {
26 crate::reflect::ReflectComponent,
27 bevy_reflect::{std_traits::ReflectDefault, Reflect},
28};
29
30#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
31use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
32
33#[derive(Component, Clone)]
41#[cfg_attr(
42 feature = "bevy_reflect",
43 derive(Reflect),
44 reflect(Component, Default, Debug, Clone, Hash, PartialEq)
45)]
46#[cfg_attr(
47 all(feature = "serialize", feature = "bevy_reflect"),
48 reflect(Deserialize, Serialize)
49)]
50pub struct Name {
51 hash: u64, name: Cow<'static, str>,
53}
54
55impl Default for Name {
56 fn default() -> Self {
57 Name::new("")
58 }
59}
60
61impl Name {
62 pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
66 let name = name.into();
67 let mut name = Name { name, hash: 0 };
68 name.update_hash();
69 name
70 }
71
72 #[inline(always)]
76 pub fn set(&mut self, name: impl Into<Cow<'static, str>>) {
77 *self = Name::new(name);
78 }
79
80 #[inline(always)]
85 pub fn mutate<F: FnOnce(&mut String)>(&mut self, f: F) {
86 f(self.name.to_mut());
87 self.update_hash();
88 }
89
90 #[inline(always)]
92 pub fn as_str(&self) -> &str {
93 &self.name
94 }
95
96 fn update_hash(&mut self) {
97 self.hash = FixedHasher.hash_one(&self.name);
98 }
99}
100
101impl core::fmt::Display for Name {
102 #[inline(always)]
103 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
104 core::fmt::Display::fmt(&self.name, f)
105 }
106}
107
108impl core::fmt::Debug for Name {
109 #[inline(always)]
110 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
111 core::fmt::Debug::fmt(&self.name, f)
112 }
113}
114
115#[derive(QueryData)]
136#[query_data(derive(Debug))]
137pub struct NameOrEntity {
138 pub name: Option<&'static Name>,
140 pub entity: Entity,
142}
143
144impl<'w, 's> core::fmt::Display for NameOrEntityItem<'w, 's> {
145 #[inline(always)]
146 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
147 match self.name {
148 Some(name) => core::fmt::Display::fmt(name, f),
149 None => core::fmt::Display::fmt(&self.entity, f),
150 }
151 }
152}
153
154impl From<&str> for Name {
157 #[inline(always)]
158 fn from(name: &str) -> Self {
159 Name::new(name.to_owned())
160 }
161}
162
163impl From<String> for Name {
164 #[inline(always)]
165 fn from(name: String) -> Self {
166 Name::new(name)
167 }
168}
169
170impl AsRef<str> for Name {
173 #[inline(always)]
174 fn as_ref(&self) -> &str {
175 &self.name
176 }
177}
178
179impl From<&Name> for String {
180 #[inline(always)]
181 fn from(val: &Name) -> String {
182 val.as_str().to_owned()
183 }
184}
185
186impl From<Name> for String {
187 #[inline(always)]
188 fn from(val: Name) -> String {
189 val.name.into_owned()
190 }
191}
192
193impl Hash for Name {
194 fn hash<H: Hasher>(&self, state: &mut H) {
195 self.name.hash(state);
196 }
197}
198
199impl PartialEq for Name {
200 fn eq(&self, other: &Self) -> bool {
201 if self.hash != other.hash {
202 return false;
204 }
205
206 self.name.eq(&other.name)
207 }
208}
209
210impl Eq for Name {}
211
212impl PartialOrd for Name {
213 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
214 Some(self.cmp(other))
215 }
216}
217
218impl Ord for Name {
219 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
220 self.name.cmp(&other.name)
221 }
222}
223
224impl Deref for Name {
225 type Target = str;
226
227 fn deref(&self) -> &Self::Target {
228 self.name.as_ref()
229 }
230}
231
232#[cfg(feature = "serialize")]
233impl Serialize for Name {
234 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
235 serializer.serialize_str(self.as_str())
236 }
237}
238
239#[cfg(feature = "serialize")]
240impl<'de> Deserialize<'de> for Name {
241 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
242 deserializer.deserialize_str(NameVisitor)
243 }
244}
245
246#[cfg(feature = "serialize")]
247struct NameVisitor;
248
249#[cfg(feature = "serialize")]
250impl<'de> Visitor<'de> for NameVisitor {
251 type Value = Name;
252
253 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
254 formatter.write_str(core::any::type_name::<Name>())
255 }
256
257 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
258 Ok(Name::new(v.to_string()))
259 }
260
261 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
262 Ok(Name::new(v))
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269 use crate::world::World;
270 use alloc::string::ToString;
271
272 #[test]
273 fn test_display_of_debug_name() {
274 let mut world = World::new();
275 let e1 = world.spawn_empty().id();
276 let name = Name::new("MyName");
277 let e2 = world.spawn(name.clone()).id();
278 let mut query = world.query::<NameOrEntity>();
279 let d1 = query.get(&world, e1).unwrap();
280 assert_eq!(d1.to_string(), "0v0");
282 let d2 = query.get(&world, e2).unwrap();
283 assert_eq!(d2.to_string(), "MyName");
285 }
286}
287
288#[cfg(all(test, feature = "serialize"))]
289mod serde_tests {
290 use super::Name;
291
292 use serde_test::{assert_tokens, Token};
293
294 #[test]
295 fn test_serde_name() {
296 let name = Name::new("MyComponent");
297 assert_tokens(&name, &[Token::String("MyComponent")]);
298 }
299}