Settings: Make serialization and deserialization more consistent
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## What problem does this solve or what need does it fill?
`bevy_settings` is someone asymmetrical in terms of how it handles serialization. This has to do with the fact that it allows multiple structs to be merged into a single TOML section, and then split apart during deserialization. For example, if we have a TOML section with properties `a`, `b`, `c`, and a settings resource with properties `a` and `d`, it will deserialize `a`, ignore `b` and `c`, and leave `d` as whatever default value it already has. Since `bevy_reflect`'s deserializer doesn't work this way (and in fact will give an error if you try this), we instead use reflection to deserialize each property individually, and then apply them to the resource one at a time.
However, in the serializer, we don't do this: instead, we serialize the whole struct, and then merge the resulting TOML Table objects. The reason we do this is because it's easier.
Unfortunately, this means that attributes such as `#[reflect(skip_serializing)]` aren't handled consistently: the serializer understands them (since it lets `bevy_reflect` handle the entire struct), but the deserializer doesn't.
## What solution would you like?
There are potentially two things we can do, one which is required, and one which is optional:
The required thing is to change the deserializer to recognize all of the `bevy_reflect` serialization attributes. This would also adding support for any future serialization attributes.
While it might seem easier to just use `bevy_reflect` to deserialize the whole struct, this won't work: we need to be able to tolerate both missing fields and extra fields, which `bevy_reflect` won't do. Nor can we take the easy path and deserialize from TOML to DynamicStruct, because there's not enough type information present to do deserialization - we don't know if "100" in TOML is an i8, u8, i32 or whatever, and `bevy_reflect` doesn't do type coercions.
The optional thing is to re-write the serializer to work the same way as the deserializer - iterating through the properties and adding them to the TOML Table one at a time. This would also require adding code to handle the serialization attributes, but the result would be serialization/deserialization that is both symmetrical and consistent.
Contributor guide
Research direction
Start in the bevy_settings serializer and deserializer, then read how bevy_reflect handles serialization attributes and TOML tables. Verify the required behavior tolerates missing and extra fields while recognizing all reflection serialization attributes; the optional goal is equivalent property-by-property serialization. Done means serialization and deserialization handle these attributes consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- game-dev
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100