Use Cow<'static, str> in Name (#1308)

* Implement Name { name } as Cow<'static, str>
* Attempt impl Reflect for Cow<'static, str.>
This commit is contained in:
Nathan Stocks 2021-01-31 17:35:23 -07:00 committed by GitHub
parent 7d065eeb71
commit 0867dc76a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 9 deletions

View File

@ -1,26 +1,27 @@
use bevy_reflect::{Reflect, ReflectComponent}; use bevy_reflect::{Reflect, ReflectComponent};
use bevy_utils::AHasher; use bevy_utils::AHasher;
use std::{ use std::{
borrow::Cow,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
ops::Deref, ops::Deref,
}; };
/// Component used to identify a entity. Stores a hash for faster comparisons /// Component used to identify an entity. Stores a hash for faster comparisons
#[derive(Debug, Clone, Reflect)] #[derive(Debug, Clone, Reflect)]
#[reflect(Component)] #[reflect(Component)]
pub struct Name { pub struct Name {
hash: u64, // TODO: Shouldn't be serialized hash: u64, // TODO: Shouldn't be serialized
name: String, name: Cow<'static, str>,
} }
impl Default for Name { impl Default for Name {
fn default() -> Self { fn default() -> Self {
Name::new("".to_string()) Name::new("")
} }
} }
impl Name { impl Name {
pub fn new(name: impl Into<String>) -> Self { pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
let name = name.into(); let name = name.into();
let mut name = Name { name, hash: 0 }; let mut name = Name { name, hash: 0 };
name.update_hash(); name.update_hash();
@ -28,19 +29,19 @@ impl Name {
} }
#[inline(always)] #[inline(always)]
pub fn set(&mut self, name: String) { pub fn set(&mut self, name: impl Into<Cow<'static, str>>) {
*self = Name::new(name); *self = Name::new(name);
} }
#[inline(always)] #[inline(always)]
pub fn mutate<F: FnOnce(&mut String)>(&mut self, f: F) { pub fn mutate<F: FnOnce(&mut String)>(&mut self, f: F) {
f(&mut self.name); f(self.name.to_mut());
self.update_hash(); self.update_hash();
} }
#[inline(always)] #[inline(always)]
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
self.name.as_str() &self.name
} }
fn update_hash(&mut self) { fn update_hash(&mut self) {
@ -89,7 +90,7 @@ impl Ord for Name {
} }
impl Deref for Name { impl Deref for Name {
type Target = String; type Target = Cow<'static, str>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.name &self.name

View File

@ -6,7 +6,12 @@ use crate::{
use bevy_reflect_derive::impl_reflect_value; use bevy_reflect_derive::impl_reflect_value;
use bevy_utils::{HashMap, HashSet}; use bevy_utils::{HashMap, HashSet};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{any::Any, hash::Hash, ops::Range}; use std::{
any::Any,
borrow::Cow,
hash::{Hash, Hasher},
ops::Range,
};
impl_reflect_value!(bool(Hash, PartialEq, Serialize, Deserialize)); impl_reflect_value!(bool(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u8(Hash, PartialEq, Serialize, Deserialize)); impl_reflect_value!(u8(Hash, PartialEq, Serialize, Deserialize));
@ -199,3 +204,63 @@ impl<K: Reflect + Clone + Eq + Hash, V: Reflect + Clone> Reflect for HashMap<K,
None None
} }
} }
impl Reflect for Cow<'static, str> {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
fn any(&self) -> &dyn Any {
self
}
fn any_mut(&mut self) -> &mut dyn Any {
self
}
fn apply(&mut self, value: &dyn Reflect) {
let value = value.any();
if let Some(value) = value.downcast_ref::<Self>() {
*self = value.clone();
} else {
panic!("Value is not a {}.", std::any::type_name::<Self>());
}
}
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
*self = value.take()?;
Ok(())
}
fn reflect_ref(&self) -> ReflectRef {
ReflectRef::Value(self)
}
fn reflect_mut(&mut self) -> ReflectMut {
ReflectMut::Value(self)
}
fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone())
}
fn reflect_hash(&self) -> Option<u64> {
let mut hasher = crate::ReflectHasher::default();
Hash::hash(&std::any::Any::type_id(self), &mut hasher);
Hash::hash(self, &mut hasher);
Some(hasher.finish())
}
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
let value = value.any();
if let Some(value) = value.downcast_ref::<Self>() {
Some(std::cmp::PartialEq::eq(self, value))
} else {
Some(false)
}
}
fn serializable(&self) -> Option<Serializable> {
Some(Serializable::Borrowed(self))
}
}