Skip to content

Commit

Permalink
bevy_reflect: implement Reflect for SmolStr
Browse files Browse the repository at this point in the history
Prompted by winit's update bevyengine#8745.
  • Loading branch information
Vrixyz committed Jun 6, 2023
1 parent d6d25d8 commit cf33bdc
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 3 deletions.
15 changes: 12 additions & 3 deletions crates/bevy_reflect/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ readme = "README.md"

[features]
default = []
# Provides Bevy-related reflection implementations
# When enabled, Provides Bevy-related reflection implementations
bevy = ["glam", "smallvec", "bevy_math"]
# When enabled, allows documentation comments to be accessed via reflection
documentation = ["bevy_reflect_derive/documentation"]
# When enabled, allows to reflect SmolStr, which bevy can expose through the winit dependency.
winit = ["smol_str"]

[dependencies]
# bevy
bevy_math = { path = "../bevy_math", version = "0.11.0-dev", features = ["serialize"], optional = true }
bevy_math = { path = "../bevy_math", version = "0.11.0-dev", features = [
"serialize",
], optional = true }
bevy_reflect_derive = { path = "bevy_reflect_derive", version = "0.11.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.11.0-dev" }
bevy_ptr = { path = "../bevy_ptr", version = "0.11.0-dev" }
Expand All @@ -30,8 +34,13 @@ parking_lot = "0.12.1"
thiserror = "1.0"
once_cell = "1.11"
serde = "1"
smallvec = { version = "1.6", features = ["serde", "union", "const_generics"], optional = true }
smallvec = { version = "1.6", features = [
"serde",
"union",
"const_generics",
], optional = true }
glam = { version = "0.24", features = ["serde"], optional = true }
smol_str = { version = "0.2.0", optional = true }

[dev-dependencies]
ron = "0.8.0"
Expand Down
134 changes: 134 additions & 0 deletions crates/bevy_reflect/src/impls/smol_str.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use std::{
any::Any,
hash::{Hash, Hasher},
};

use smol_str::SmolStr;

use crate::{
utility::{reflect_hasher, NonGenericTypeInfoCell},
FromReflect, FromType, GetTypeRegistration, Reflect, ReflectDeserialize, ReflectFromPtr,
ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, TypeInfo, TypeRegistration, Typed,
ValueInfo,
};

impl Reflect for SmolStr {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}

fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
Some(<Self as Typed>::type_info())
}

fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}

fn as_any(&self) -> &dyn Any {
self
}

fn as_any_mut(&mut self) -> &mut dyn Any {
self
}

fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
self
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}

fn apply(&mut self, value: &dyn Reflect) {
let value = value.as_any();
if let Some(value) = value.downcast_ref::<String>() {
*self = SmolStr::new(value);
} 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 reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Value(self)
}

fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone())
}

fn reflect_hash(&self) -> Option<u64> {
let mut hasher = reflect_hasher();
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.as_any();
if let Some(value) = value.downcast_ref::<Self>() {
Some(std::cmp::PartialEq::eq(self, value))
} else {
Some(false)
}
}
}

impl Typed for SmolStr {
fn type_info() -> &'static TypeInfo {
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::<Self>()))
}
}

impl GetTypeRegistration for SmolStr {
fn get_type_registration() -> TypeRegistration {
let mut registration = TypeRegistration::of::<Self>();
#[cfg(feature = "serde")]
{
registration.insert::<ReflectDeserialize>(FromType::<Self>::from_type());
registration.insert::<ReflectSerialize>(FromType::<Self>::from_type());
}
registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
registration
}
}

impl FromReflect for SmolStr {
fn from_reflect(reflect: &dyn crate::Reflect) -> Option<Self> {
Some(reflect.as_any().downcast_ref::<String>()?.into())
}
}

#[cfg(test)]
mod tests {
use crate::Reflect;
use smol_str::SmolStr;

#[test]
fn should_partial_eq_smolstr() {
let a: &dyn Reflect = &SmolStr::new("A");
let b: &dyn Reflect = &SmolStr::new("A");
let c: &dyn Reflect = &SmolStr::new("B");
assert!(a.reflect_partial_eq(b).unwrap_or_default());
assert!(!a.reflect_partial_eq(c).unwrap_or_default());
}
}
3 changes: 3 additions & 0 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,9 @@ mod impls {
mod rect;
#[cfg(feature = "smallvec")]
mod smallvec;
#[cfg(feature = "smol_str")]
mod smol_str;

mod std;

#[cfg(feature = "glam")]
Expand Down

0 comments on commit cf33bdc

Please sign in to comment.