Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bevy_reflect: implement Reflect for SmolStr #8771

Merged
merged 9 commits into from
Jun 8, 2023
Merged
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
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
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.
Vrixyz marked this conversation as resolved.
Show resolved Hide resolved
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
Vrixyz marked this conversation as resolved.
Show resolved Hide resolved
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>());
}
Vrixyz marked this conversation as resolved.
Show resolved Hide resolved
}

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());
}
Vrixyz marked this conversation as resolved.
Show resolved Hide resolved
registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
Vrixyz marked this conversation as resolved.
Show resolved Hide resolved
registration
}
}

impl FromReflect for SmolStr {
fn from_reflect(reflect: &dyn crate::Reflect) -> Option<Self> {
Some(reflect.as_any().downcast_ref::<String>()?.into())
}
Vrixyz marked this conversation as resolved.
Show resolved Hide resolved
}

#[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());
Vrixyz marked this conversation as resolved.
Show resolved Hide resolved
}
}
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