1#[cfg(feature = "bevy_reflect")]
2use bevy_ecs::reflect::ReflectComponent;
3use bevy_ecs::{component::Component, entity::Entity, query::QueryData};
4
5use alloc::borrow::Cow;
6#[cfg(feature = "bevy_reflect")]
7use bevy_reflect::std_traits::ReflectDefault;
8#[cfg(feature = "bevy_reflect")]
9use bevy_reflect::Reflect;
10use bevy_utils::AHasher;
11use core::{
12 hash::{Hash, Hasher},
13 ops::Deref,
14};
15
16#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
17use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
18
19#[derive(Component, Clone)]
27#[cfg_attr(
28 feature = "bevy_reflect",
29 derive(Reflect),
30 reflect(Component, Default, Debug)
31)]
32#[cfg_attr(
33 all(feature = "serialize", feature = "bevy_reflect"),
34 reflect(Deserialize, Serialize)
35)]
36pub struct Name {
37 hash: u64, name: Cow<'static, str>,
39}
40
41impl Default for Name {
42 fn default() -> Self {
43 Name::new("")
44 }
45}
46
47impl Name {
48 pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
52 let name = name.into();
53 let mut name = Name { name, hash: 0 };
54 name.update_hash();
55 name
56 }
57
58 #[inline(always)]
62 pub fn set(&mut self, name: impl Into<Cow<'static, str>>) {
63 *self = Name::new(name);
64 }
65
66 #[inline(always)]
71 pub fn mutate<F: FnOnce(&mut String)>(&mut self, f: F) {
72 f(self.name.to_mut());
73 self.update_hash();
74 }
75
76 #[inline(always)]
78 pub fn as_str(&self) -> &str {
79 &self.name
80 }
81
82 fn update_hash(&mut self) {
83 let mut hasher = AHasher::default();
84 self.name.hash(&mut hasher);
85 self.hash = hasher.finish();
86 }
87}
88
89impl core::fmt::Display for Name {
90 #[inline(always)]
91 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
92 core::fmt::Display::fmt(&self.name, f)
93 }
94}
95
96impl core::fmt::Debug for Name {
97 #[inline(always)]
98 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
99 core::fmt::Debug::fmt(&self.name, f)
100 }
101}
102
103#[derive(QueryData)]
125#[query_data(derive(Debug))]
126pub struct NameOrEntity {
127 pub name: Option<&'static Name>,
129 pub entity: Entity,
131}
132
133impl<'a> core::fmt::Display for NameOrEntityItem<'a> {
134 #[inline(always)]
135 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
136 match self.name {
137 Some(name) => core::fmt::Display::fmt(name, f),
138 None => core::fmt::Display::fmt(&self.entity, f),
139 }
140 }
141}
142
143impl From<&str> for Name {
146 #[inline(always)]
147 fn from(name: &str) -> Self {
148 Name::new(name.to_owned())
149 }
150}
151impl From<String> for Name {
152 #[inline(always)]
153 fn from(name: String) -> Self {
154 Name::new(name)
155 }
156}
157
158impl AsRef<str> for Name {
161 #[inline(always)]
162 fn as_ref(&self) -> &str {
163 &self.name
164 }
165}
166impl From<&Name> for String {
167 #[inline(always)]
168 fn from(val: &Name) -> String {
169 val.as_str().to_owned()
170 }
171}
172impl From<Name> for String {
173 #[inline(always)]
174 fn from(val: Name) -> String {
175 val.name.into_owned()
176 }
177}
178
179impl Hash for Name {
180 fn hash<H: Hasher>(&self, state: &mut H) {
181 self.name.hash(state);
182 }
183}
184
185impl PartialEq for Name {
186 fn eq(&self, other: &Self) -> bool {
187 if self.hash != other.hash {
188 return false;
190 }
191
192 self.name.eq(&other.name)
193 }
194}
195
196impl Eq for Name {}
197
198impl PartialOrd for Name {
199 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
200 Some(self.cmp(other))
201 }
202}
203
204impl Ord for Name {
205 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
206 self.name.cmp(&other.name)
207 }
208}
209
210impl Deref for Name {
211 type Target = str;
212
213 fn deref(&self) -> &Self::Target {
214 self.name.as_ref()
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221 use bevy_ecs::world::World;
222
223 #[test]
224 fn test_display_of_debug_name() {
225 let mut world = World::new();
226 let e1 = world.spawn_empty().id();
227 let name = Name::new("MyName");
228 let e2 = world.spawn(name.clone()).id();
229 let mut query = world.query::<NameOrEntity>();
230 let d1 = query.get(&world, e1).unwrap();
231 let d2 = query.get(&world, e2).unwrap();
232 assert_eq!(d1.to_string(), "0v1");
234 assert_eq!(d2.to_string(), "MyName");
236 }
237}