diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 85f63be654340..72cedace371cb 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -15,6 +15,7 @@ use crate::{ TypeRegistration, TypeRegistry, Typed, ValueInfo, }; use bevy_reflect_derive::{impl_reflect, impl_reflect_value}; + use std::fmt; use std::{ any::Any, @@ -99,6 +100,7 @@ impl_reflect_value!(::std::path::PathBuf( Deserialize, Default )); +impl_reflect_value!(::core::marker::PhantomData); impl_reflect_value!(::std::any::TypeId(Debug, Hash, PartialEq,)); impl_reflect_value!(::std::collections::BTreeSet()); impl_reflect_value!(::core::ops::Range()); diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index bc3137d0b2b55..0a39a6e25c480 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -14,6 +14,7 @@ mod tests { type_registry::TypeRegistry, DynamicStruct, FromReflect, Reflect, }; + use bevy_reflect_derive::TypePath; use serde::de::DeserializeSeed; #[test] @@ -183,4 +184,85 @@ mod tests { .reflect_partial_eq(result.as_partial_reflect()) .unwrap()); } + + #[test] + fn should_roundtrip_ref_phantom_data() { + use core::marker::PhantomData; + + #[derive(Reflect, ::serde::Serialize, ::serde::Deserialize)] + struct TestStruct<'a, T> { + a: i32, + _marker: PhantomData<&'a T>, + } + + #[derive(Reflect)] + struct MarkerType; + + let mut registry = TypeRegistry::default(); + registry.register::>(); + + let value: DynamicStruct = TestStruct::<'static, MarkerType> { + a: 123, + _marker: PhantomData, + } + .clone_dynamic(); + + let serializer = ReflectSerializer::new(&value, ®istry); + + let expected = r#"{"bevy_reflect::serde::tests::TestStruct":(a:123)}"#; + let result = ron::ser::to_string(&serializer).unwrap(); + assert_eq!(expected, result); + + let mut deserializer = ron::de::Deserializer::from_str(&result).unwrap(); + let reflect_deserializer = ReflectDeserializer::new(®istry); + + let expected = value.clone_value(); + let result = reflect_deserializer.deserialize(&mut deserializer).unwrap(); + + assert!(expected + .reflect_partial_eq(result.as_partial_reflect()) + .unwrap()); + } + + #[test] + fn should_roundtrip_phantom_data() { + use core::marker::PhantomData; + + #[derive(Reflect, ::serde::Serialize, ::serde::Deserialize)] + struct TestStruct { + a: i32, + _marker: PhantomData, + } + + #[derive(Reflect)] + struct MarkerType; + + let mut registry = TypeRegistry::default(); + registry.register::>(); + registry.register::>(); + registry.register_type_data::, crate::ReflectDeserialize>(); + registry.register_type_data::, crate::ReflectDeserialize>(); + + let value: DynamicStruct = TestStruct:: { + a: 123, + _marker: PhantomData, + } + .clone_dynamic(); + + let serializer = ReflectSerializer::new(&value, ®istry); + + let expected = r#"{"bevy_reflect::serde::tests::TestStruct":(a:123)}"#; + let result = ron::ser::to_string(&serializer).unwrap(); + assert_eq!(expected, result); + + let mut deserializer = ron::de::Deserializer::from_str(&result).unwrap(); + let reflect_deserializer = ReflectDeserializer::new(®istry); + + let expected = value.clone_value(); + let result = reflect_deserializer.deserialize(&mut deserializer).unwrap(); + + assert!(expected + .reflect_partial_eq(result.as_partial_reflect()) + .unwrap()); + } }