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<'a> core::fmt::Display for NameOrEntityItem<'a> {
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}
162impl From<String> for Name {
163 #[inline(always)]
164 fn from(name: String) -> Self {
165 Name::new(name)
166 }
167}
168
169impl AsRef<str> for Name {
172 #[inline(always)]
173 fn as_ref(&self) -> &str {
174 &self.name
175 }
176}
177impl From<&Name> for String {
178 #[inline(always)]
179 fn from(val: &Name) -> String {
180 val.as_str().to_owned()
181 }
182}
183impl From<Name> for String {
184 #[inline(always)]
185 fn from(val: Name) -> String {
186 val.name.into_owned()
187 }
188}
189
190impl Hash for Name {
191 fn hash<H: Hasher>(&self, state: &mut H) {
192 self.name.hash(state);
193 }
194}
195
196impl PartialEq for Name {
197 fn eq(&self, other: &Self) -> bool {
198 if self.hash != other.hash {
199 return false;
201 }
202
203 self.name.eq(&other.name)
204 }
205}
206
207impl Eq for Name {}
208
209impl PartialOrd for Name {
210 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
211 Some(self.cmp(other))
212 }
213}
214
215impl Ord for Name {
216 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
217 self.name.cmp(&other.name)
218 }
219}
220
221impl Deref for Name {
222 type Target = str;
223
224 fn deref(&self) -> &Self::Target {
225 self.name.as_ref()
226 }
227}
228
229#[cfg(feature = "serialize")]
230impl Serialize for Name {
231 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
232 serializer.serialize_str(self.as_str())
233 }
234}
235
236#[cfg(feature = "serialize")]
237impl<'de> Deserialize<'de> for Name {
238 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
239 deserializer.deserialize_str(NameVisitor)
240 }
241}
242
243#[cfg(feature = "serialize")]
244struct NameVisitor;
245
246#[cfg(feature = "serialize")]
247impl<'de> Visitor<'de> for NameVisitor {
248 type Value = Name;
249
250 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
251 formatter.write_str(core::any::type_name::<Name>())
252 }
253
254 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
255 Ok(Name::new(v.to_string()))
256 }
257
258 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
259 Ok(Name::new(v))
260 }
261}
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266 use crate::world::World;
267 use alloc::string::ToString;
268
269 #[test]
270 fn test_display_of_debug_name() {
271 let mut world = World::new();
272 let e1 = world.spawn_empty().id();
273 let name = Name::new("MyName");
274 let e2 = world.spawn(name.clone()).id();
275 let mut query = world.query::<NameOrEntity>();
276 let d1 = query.get(&world, e1).unwrap();
277 let d2 = query.get(&world, e2).unwrap();
278 assert_eq!(d1.to_string(), "0v1");
280 assert_eq!(d2.to_string(), "MyName");
282 }
283}
284
285#[cfg(all(test, feature = "serialize"))]
286mod serde_tests {
287 use super::Name;
288
289 use serde_test::{assert_tokens, Token};
290
291 #[test]
292 fn test_serde_name() {
293 let name = Name::new("MyComponent");
294 assert_tokens(&name, &[Token::String("MyComponent")]);
295 }
296}