bevy_reflect: Improve reflection serialization error messages (#13867)

# Objective

The error messages that appear when a value cannot be serialized or
deserialized via reflection could be slightly improved.

When one of these operations fails, some users are confused about how to
resolve the issue. I've spoken with a few who didn't know they could
register `ReflectSerialize` themselves. We should try to clarify this to
some degree in the error messages.

## Solution

Add some more detail to the error messages.

For example, replacing this:

```
Type 'core::ops::RangeInclusive<f32>' did not register ReflectSerialize
```

with this:

```
Type `core::ops::RangeInclusive<f32>` did not register the `ReflectSerialize` type data. For certain types, this may need to be registered manually using `register_type_data`
```

I also added a separate error message if the type was not registered in
the type registry at all:

```
Type `core::ops::RangeInclusive<f32>` is not registered in the type registry
```

## Testing

You can test locally by running:

```
cargo test --package bevy_reflect
```

---

## Changelog

- Added error message for missing type registration when serializing
reflect data
- Changed error message for missing `ReflectSerialize` registration when
serializing reflect data
- Changed error message for missing `ReflectDeserialize` registration
when deserializing reflect data
This commit is contained in:
Gino Valente 2024-06-17 11:13:46 -07:00 committed by GitHub
parent 6273227e09
commit 53910e07ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 63 additions and 9 deletions

View File

@ -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 = <MyStruct as FromReflect>::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::<RangeInclusive<f32>>();
let input = r#"{"core::ops::RangeInclusive<f32>":(start:0.0,end:1.0)}"#;
let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
let reflect_deserializer = ReflectDeserializer::new(&registry);
let error = reflect_deserializer
.deserialize(&mut deserializer)
.unwrap_err();
assert_eq!(error, ron::Error::Message("Type `core::ops::RangeInclusive<f32>` did not register the `ReflectDeserialize` type data. For certain types, this may need to be registered manually using `register_type_data`".to_string()));
}
}

View File

@ -39,14 +39,20 @@ fn get_serializable<'a, E: Error>(
))
})?;
let reflect_serialize = type_registry
.get_type_data::<ReflectSerialize>(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::<ReflectSerialize>().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::<f32>::new(0.0, 1.0);
let registry = TypeRegistry::new();
let serializer = ReflectSerializer::new(&value, &registry);
let error = ron::ser::to_string(&serializer).unwrap_err();
assert_eq!(
error,
ron::Error::Message(
"Type `core::ops::RangeInclusive<f32>` is not registered in the type registry"
.to_string()
)
);
}
#[test]
fn should_return_error_if_missing_type_data() {
let value = RangeInclusive::<f32>::new(0.0, 1.0);
let mut registry = TypeRegistry::new();
registry.register::<RangeInclusive<f32>>();
let serializer = ReflectSerializer::new(&value, &registry);
let error = ron::ser::to_string(&serializer).unwrap_err();
assert_eq!(
error,
ron::Error::Message(
"Type `core::ops::RangeInclusive<f32>` did not register the `ReflectSerialize` type data. For certain types, this may need to be registered manually using `register_type_data`".to_string()
)
);
}
}