diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 3087298a8d..62948f74ad 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -620,7 +620,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { TypeInfo::Value(_) => { // This case should already be handled Err(Error::custom(format_args!( - "the TypeRegistration for {type_path} doesn't have ReflectDeserialize", + "Type `{type_path}` did not register the `ReflectDeserialize` type data. For certain types, this may need to be registered manually using `register_type_data`", ))) } } @@ -1174,6 +1174,7 @@ mod tests { use bincode::Options; use std::any::TypeId; use std::f32::consts::PI; + use std::ops::RangeInclusive; use serde::de::DeserializeSeed; use serde::Deserialize; @@ -1632,4 +1633,18 @@ mod tests { let output = ::from_reflect(dynamic_output.as_ref()).unwrap(); assert_eq!(expected, output); } + + #[test] + fn should_return_error_if_missing_type_data() { + let mut registry = TypeRegistry::new(); + registry.register::>(); + + let input = r#"{"core::ops::RangeInclusive":(start:0.0,end:1.0)}"#; + let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); + let reflect_deserializer = ReflectDeserializer::new(®istry); + let error = reflect_deserializer + .deserialize(&mut deserializer) + .unwrap_err(); + assert_eq!(error, ron::Error::Message("Type `core::ops::RangeInclusive` did not register the `ReflectDeserialize` type data. For certain types, this may need to be registered manually using `register_type_data`".to_string())); + } } diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 08e124945c..8608b36361 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -39,14 +39,20 @@ fn get_serializable<'a, E: Error>( )) })?; - let reflect_serialize = type_registry - .get_type_data::(info.type_id()) - .ok_or_else(|| { - Error::custom(format_args!( - "Type '{}' did not register ReflectSerialize", - info.type_path(), - )) - })?; + let registration = type_registry.get(info.type_id()).ok_or_else(|| { + Error::custom(format_args!( + "Type `{}` is not registered in the type registry", + info.type_path(), + )) + })?; + + let reflect_serialize = registration.data::().ok_or_else(|| { + Error::custom(format_args!( + "Type `{}` did not register the `ReflectSerialize` type data. For certain types, this may need to be registered manually using `register_type_data`", + info.type_path(), + )) + })?; + Ok(reflect_serialize.get_serializable(reflect_value)) } @@ -543,6 +549,7 @@ mod tests { use ron::ser::PrettyConfig; use serde::Serialize; use std::f32::consts::PI; + use std::ops::RangeInclusive; #[derive(Reflect, Debug, PartialEq)] struct MyStruct { @@ -932,4 +939,36 @@ mod tests { assert_eq!(expected, output); } + + #[test] + fn should_return_error_if_missing_registration() { + let value = RangeInclusive::::new(0.0, 1.0); + let registry = TypeRegistry::new(); + + let serializer = ReflectSerializer::new(&value, ®istry); + let error = ron::ser::to_string(&serializer).unwrap_err(); + assert_eq!( + error, + ron::Error::Message( + "Type `core::ops::RangeInclusive` is not registered in the type registry" + .to_string() + ) + ); + } + + #[test] + fn should_return_error_if_missing_type_data() { + let value = RangeInclusive::::new(0.0, 1.0); + let mut registry = TypeRegistry::new(); + registry.register::>(); + + let serializer = ReflectSerializer::new(&value, ®istry); + let error = ron::ser::to_string(&serializer).unwrap_err(); + assert_eq!( + error, + ron::Error::Message( + "Type `core::ops::RangeInclusive` did not register the `ReflectSerialize` type data. For certain types, this may need to be registered manually using `register_type_data`".to_string() + ) + ); + } }