1use bevy_ecs::query::QueryData;
2use bevy_ecs::{component::Component, entity::Entity, reflect::ReflectComponent};
3
4use bevy_reflect::std_traits::ReflectDefault;
5use bevy_reflect::Reflect;
6use bevy_utils::AHasher;
7use std::{
8 borrow::Cow,
9 hash::{Hash, Hasher},
10 ops::Deref,
11};
12
13#[cfg(feature = "serialize")]
14use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
15
16#[derive(Reflect, Component, Clone)]
24#[reflect(Component, Default, Debug)]
25#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
26pub struct Name {
27 hash: u64, name: Cow<'static, str>,
29}
30
31impl Default for Name {
32 fn default() -> Self {
33 Name::new("")
34 }
35}
36
37impl Name {
38 pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
42 let name = name.into();
43 let mut name = Name { name, hash: 0 };
44 name.update_hash();
45 name
46 }
47
48 #[inline(always)]
52 pub fn set(&mut self, name: impl Into<Cow<'static, str>>) {
53 *self = Name::new(name);
54 }
55
56 #[inline(always)]
61 pub fn mutate<F: FnOnce(&mut String)>(&mut self, f: F) {
62 f(self.name.to_mut());
63 self.update_hash();
64 }
65
66 #[inline(always)]
68 pub fn as_str(&self) -> &str {
69 &self.name
70 }
71
72 fn update_hash(&mut self) {
73 let mut hasher = AHasher::default();
74 self.name.hash(&mut hasher);
75 self.hash = hasher.finish();
76 }
77}
78
79impl std::fmt::Display for Name {
80 #[inline(always)]
81 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
82 std::fmt::Display::fmt(&self.name, f)
83 }
84}
85
86impl std::fmt::Debug for Name {
87 #[inline(always)]
88 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
89 std::fmt::Debug::fmt(&self.name, f)
90 }
91}
92
93#[derive(QueryData)]
110pub struct DebugName {
111 pub name: Option<&'static Name>,
113 pub entity: Entity,
115}
116
117impl<'a> std::fmt::Debug for DebugNameItem<'a> {
118 #[inline(always)]
119 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
120 match self.name {
121 Some(name) => write!(f, "{:?} ({:?})", &name, &self.entity),
122 None => std::fmt::Debug::fmt(&self.entity, f),
123 }
124 }
125}
126
127impl From<&str> for Name {
130 #[inline(always)]
131 fn from(name: &str) -> Self {
132 Name::new(name.to_owned())
133 }
134}
135impl From<String> for Name {
136 #[inline(always)]
137 fn from(name: String) -> Self {
138 Name::new(name)
139 }
140}
141
142impl AsRef<str> for Name {
145 #[inline(always)]
146 fn as_ref(&self) -> &str {
147 &self.name
148 }
149}
150impl From<&Name> for String {
151 #[inline(always)]
152 fn from(val: &Name) -> String {
153 val.as_str().to_owned()
154 }
155}
156impl From<Name> for String {
157 #[inline(always)]
158 fn from(val: Name) -> String {
159 val.name.into_owned()
160 }
161}
162
163impl Hash for Name {
164 fn hash<H: Hasher>(&self, state: &mut H) {
165 self.name.hash(state);
166 }
167}
168
169impl PartialEq for Name {
170 fn eq(&self, other: &Self) -> bool {
171 if self.hash != other.hash {
172 return false;
174 }
175
176 self.name.eq(&other.name)
177 }
178}
179
180impl Eq for Name {}
181
182impl PartialOrd for Name {
183 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
184 Some(self.cmp(other))
185 }
186}
187
188impl Ord for Name {
189 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
190 self.name.cmp(&other.name)
191 }
192}
193
194impl Deref for Name {
195 type Target = str;
196
197 fn deref(&self) -> &Self::Target {
198 self.name.as_ref()
199 }
200}