Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 80 additions & 1 deletion crates/bevy_reflect/src/impls/std.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{self as bevy_reflect, ReflectFromPtr};
use crate::{self as bevy_reflect, ReflectFromPtr, Wrapper, WrapperInfo};
use crate::{
map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, Enum,
EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, MapIter,
Expand Down Expand Up @@ -891,6 +891,85 @@ impl FromReflect for Cow<'static, str> {
}
}

impl<T: Reflect> Typed for Box<T> {
fn type_info() -> &'static TypeInfo {
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
CELL.get_or_set(|| TypeInfo::Wrapper(WrapperInfo::new::<Self, T>()))
}
}

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

fn get_type_info(&self) -> &'static TypeInfo {
<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 as_reflect(&self) -> &dyn Reflect {
self
}

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

fn apply(&mut self, value: &dyn Reflect) {
match value.reflect_ref() {
ReflectRef::Wrapper(wrapper) => {
(**self).apply(wrapper.get());
}
_ => 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::<Self>()?;
Ok(())
}

fn reflect_ref(&self) -> ReflectRef {
ReflectRef::Wrapper(self)
}

fn reflect_mut(&mut self) -> ReflectMut {
ReflectMut::Wrapper(self)
}

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

impl<T: Reflect> Wrapper for Box<T> {
fn get(&self) -> &dyn Reflect {
&**self
}

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

impl<T: Reflect> GetTypeRegistration for Box<T> {
fn get_type_registration() -> TypeRegistration {
TypeRegistration::of::<Self>()
}
}

#[cfg(test)]
mod tests {
use crate as bevy_reflect;
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ mod tuple_struct;
mod type_info;
mod type_registry;
mod type_uuid;
mod wrapper;

mod impls {
#[cfg(feature = "glam")]
mod glam;
Expand Down Expand Up @@ -58,6 +60,7 @@ pub use tuple_struct::*;
pub use type_info::*;
pub use type_registry::*;
pub use type_uuid::*;
pub use wrapper::*;

pub use bevy_reflect_derive::*;
pub use erased_serde;
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_reflect/src/reflect.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug,
tuple_struct_debug, Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, Typed,
ValueInfo,
ValueInfo, Wrapper,
};
use std::{
any::{self, Any, TypeId},
Expand All @@ -24,6 +24,7 @@ pub enum ReflectRef<'a> {
List(&'a dyn List),
Array(&'a dyn Array),
Map(&'a dyn Map),
Wrapper(&'a dyn Wrapper),
Enum(&'a dyn Enum),
Value(&'a dyn Reflect),
}
Expand All @@ -42,6 +43,7 @@ pub enum ReflectMut<'a> {
Array(&'a mut dyn Array),
Map(&'a mut dyn Map),
Enum(&'a mut dyn Enum),
Wrapper(&'a mut dyn Wrapper),
Value(&'a mut dyn Reflect),
}

Expand Down
24 changes: 20 additions & 4 deletions crates/bevy_reflect/src/serde/de.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::serde::SerializationData;
use crate::{
ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple,
DynamicTupleStruct, DynamicVariant, EnumInfo, ListInfo, Map, MapInfo, NamedField, Reflect,
ReflectDeserialize, StructInfo, StructVariantInfo, Tuple, TupleInfo, TupleStruct,
TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, UnnamedField,
VariantInfo,
DynamicTupleStruct, DynamicVariant, DynamicWrapper, EnumInfo, ListInfo, Map, MapInfo,
NamedField, Reflect, ReflectDeserialize, StructInfo, StructVariantInfo, Tuple, TupleInfo,
TupleStruct, TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry,
UnnamedField, VariantInfo,
};
use erased_serde::Deserializer;
use serde::de::{
Expand Down Expand Up @@ -361,6 +361,22 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
dynamic_enum.set_name(type_name.to_string());
Ok(Box::new(dynamic_enum))
}
TypeInfo::Wrapper(wrapper_info) => {
let registration = get_registration(
wrapper_info.inner_type_id(),
wrapper_info.inner_type_name(),
self.registry,
)?;
let inner = TypedReflectDeserializer {
registration,
registry: self.registry,
}
.deserialize(deserializer)?;

let dynamic_wrapper =
DynamicWrapper::new(wrapper_info.type_name().to_string(), inner);
Ok(Box::new(dynamic_wrapper))
}
TypeInfo::Value(_) => {
// This case should already be handled
Err(de::Error::custom(format_args!(
Expand Down
21 changes: 20 additions & 1 deletion crates/bevy_reflect/src/serde/ser.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
Array, Enum, List, Map, Reflect, ReflectRef, ReflectSerialize, Struct, Tuple, TupleStruct,
TypeInfo, TypeRegistry, VariantInfo, VariantType,
TypeInfo, TypeRegistry, VariantInfo, VariantType, Wrapper,
};
use serde::ser::{
Error, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct,
Expand Down Expand Up @@ -156,6 +156,11 @@ impl<'a> Serialize for TypedReflectSerializer<'a> {
registry: self.registry,
}
.serialize(serializer),
ReflectRef::Wrapper(value) => WrapperSerializer {
wrapper: value,
registry: self.registry,
}
.serialize(serializer),
ReflectRef::Value(_) => Err(serializable.err().unwrap()),
}
}
Expand Down Expand Up @@ -466,6 +471,20 @@ impl<'a> Serialize for ArraySerializer<'a> {
}
}

pub struct WrapperSerializer<'a> {
pub wrapper: &'a dyn Wrapper,
pub registry: &'a TypeRegistry,
}

impl<'a> Serialize for WrapperSerializer<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
TypedReflectSerializer::new(self.wrapper.get(), self.registry).serialize(serializer)
}
}

#[cfg(test)]
mod tests {
use crate as bevy_reflect;
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_reflect/src/type_info.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo,
WrapperInfo,
};
use std::any::{Any, TypeId};

Expand Down Expand Up @@ -102,6 +103,7 @@ pub enum TypeInfo {
Array(ArrayInfo),
Map(MapInfo),
Enum(EnumInfo),
Wrapper(WrapperInfo),
Value(ValueInfo),
/// Type information for "dynamic" types whose metadata can't be known at compile-time.
///
Expand All @@ -120,6 +122,7 @@ impl TypeInfo {
Self::Array(info) => info.type_id(),
Self::Map(info) => info.type_id(),
Self::Enum(info) => info.type_id(),
Self::Wrapper(info) => info.type_id(),
Self::Value(info) => info.type_id(),
Self::Dynamic(info) => info.type_id(),
}
Expand All @@ -137,6 +140,7 @@ impl TypeInfo {
Self::Array(info) => info.type_name(),
Self::Map(info) => info.type_name(),
Self::Enum(info) => info.type_name(),
Self::Wrapper(info) => info.type_name(),
Self::Value(info) => info.type_name(),
Self::Dynamic(info) => info.type_name(),
}
Expand Down
Loading