bevy_reflect: Add ReflectDeserializerProcessor (#15482)

**NOTE: Also see https://github.com/bevyengine/bevy/pull/15548 for the
serializer equivalent**

# Objective

The current `ReflectDeserializer` and `TypedReflectDeserializer` use the
`TypeRegistration` and/or `ReflectDeserialize` of a given type in order
to determine how to deserialize a value of that type. However, there is
currently no way to statefully override deserialization of a given type
when using these two deserializers - that is, to have some local data in
the same scope as the `ReflectDeserializer`, and make use of that data
when deserializing.

The motivating use case for this came up when working on
[`bevy_animation_graph`](https://github.com/aecsocket/bevy_animation_graph/tree/feat/dynamic-nodes),
when loading an animation graph asset. The `AnimationGraph` stores
`Vec<Box<dyn NodeLike>>`s which we have to load in. Those `Box<dyn
NodeLike>`s may store `Handle`s to e.g. `Handle<AnimationClip>`. I want
to trigger a `load_context.load()` for that handle when it's loaded.
```rs
#[derive(Reflect)]
struct Animation {
    clips: Vec<Handle<AnimationClip>>,
}
```
```rs
(
    clips: [
        "animation_clips/walk.animclip.ron",
        "animation_clips/run.animclip.ron",
        "animation_clips/jump.animclip.ron",
    ],
)
````
Currently, if this were deserialized from an asset loader, this would be
deserialized as a vec of `Handle::default()`s, which isn't useful since
we also need to `load_context.load()` those handles for them to be used.
With this processor field, a processor can detect when `Handle<T>`s are
being loaded, then actually load them in.

## Solution

```rs
trait ReflectDeserializerProcessor {
    fn try_deserialize<'de, D>(
        &mut self,
        registration: &TypeRegistration,
        deserializer: D,
    ) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
    where
        D: serde::Deserializer<'de>;
}
```
```diff
- pub struct ReflectDeserializer<'a> {
+ pub struct ReflectDeserializer<'a, P = ()> { // also for ReflectTypedDeserializer
      registry: &'a TypeRegistry,
+     processor: Option<&'a mut P>,
  }
```
```rs
impl<'a, P: ReflectDeserializerProcessor> ReflectDeserializer<'a, P> { // also for ReflectTypedDeserializer
    pub fn with_processor(registry: &'a TypeRegistry, processor: &'a mut P) -> Self {
        Self {
            registry,
            processor: Some(processor),
        }
    }
}
```
This does not touch the existing `fn new`s.
This `processor` field is also added to all internal visitor structs.

When `TypedReflectDeserializer` runs, it will first try to deserialize a
value of this type by passing the `TypeRegistration` and deserializer to
the processor, and fallback to the default logic. This processor runs
the earliest, and takes priority over all other deserialization logic.

## Testing

Added unit tests to `bevy_reflect::serde::de`. Also using almost exactly
the same implementation in [my fork of
`bevy_animation_graph`](https://github.com/aecsocket/bevy_animation_graph/tree/feat/dynamic-nodes).

## Migration Guide

(Since I added `P = ()`, I don't think this is actually a breaking
change anymore, but I'll leave this in)

`bevy_reflect`'s `ReflectDeserializer` and `TypedReflectDeserializer`
now take a `ReflectDeserializerProcessor` as the type parameter `P`,
which allows you to customize deserialization for specific types when
they are found. However, the rest of the API surface (`new`) remains the
same.

<details>
<summary>Original implementation</summary>

Add `ReflectDeserializerProcessor`:
```rs
struct ReflectDeserializerProcessor {
    pub can_deserialize: Box<dyn FnMut(&TypeRegistration) -> bool + 'p>,
    pub deserialize: Box<
        dyn FnMut(
                &TypeRegistration,
                &mut dyn erased_serde::Deserializer,
            ) -> Result<Box<dyn PartialReflect>, erased_serde::Error>
            + 'p,
}
``` 

Along with `ReflectDeserializer::new_with_processor` and
`TypedReflectDeserializer::new_with_processor`. This does not touch the
public API of the existing `new` fns.

This is stored as an `Option<&mut ReflectDeserializerProcessor>` on the
deserializer and any of the private `-Visitor` structs, and when we
attempt to deserialize a value, we first pass it through this processor.

Also added a very comprehensive doc test to
`ReflectDeserializerProcessor`, which is actually a scaled down version
of the code for the `bevy_animation_graph` loader. This should give
users a good motivating example for when and why to use this feature.

### Why `Box<dyn ..>`?

When I originally implemented this, I added a type parameter to
`ReflectDeserializer` to determine the processor used, with `()` being
"no processor". However when using this, I kept running into rustc
errors where it failed to validate certain type bounds and led to
overflows. I then switched to a dynamic dispatch approach.

The dynamic dispatch should not be that expensive, nor should it be a
performance regression, since it's only used if there is `Some`
processor. (Note: I have not benchmarked this, I am just speculating.)
Also, it means that we don't infect the rest of the code with an extra
type parameter, which is nicer to maintain.

### Why the `'p` on `ReflectDeserializerProcessor<'p>`?

Without a lifetime here, the `Box`es would automatically become `Box<dyn
FnMut(..) + 'static>`. This makes them practically useless, since any
local data you would want to pass in must then be `'static`. In the
motivating example, you couldn't pass in that `&mut LoadContext` to the
function.

This means that the `'p` infects the rest of the Visitor types, but this
is acceptable IMO. This PR also elides the lifetimes in the `impl<'de>
Visitor<'de> for -Visitor` blocks where possible.

### Future possibilities

I think it's technically possible to turn the processor into a trait,
and make the deserializers generic over that trait. This would also open
the door to an API like:
```rs
type Seed;

fn seed_deserialize(&mut self, r: &TypeRegistration) -> Option<Self::Seed>;

fn deserialize(&mut self, r: &TypeRegistration, d: &mut dyn erased_serde::Deserializer, s: Self::Seed) -> ...;
```

A similar processor system should also be added to the serialization
side, but that's for another PR. Ideally, both PRs will be in the same
release, since one isn't very useful without the other.

## Testing

Added unit tests to `bevy_reflect::serde::de`. Also using almost exactly
the same implementation in [my fork of
`bevy_animation_graph`](https://github.com/aecsocket/bevy_animation_graph/tree/feat/dynamic-nodes).

## Migration Guide

`bevy_reflect`'s `ReflectDeserializer` and `TypedReflectDeserializer`
now take a second lifetime parameter `'p` for storing the
`ReflectDeserializerProcessor` field lifetimes. However, the rest of the
API surface (`new`) remains the same, so if you are not storing these
deserializers or referring to them with lifetimes, you should not have
to make any changes.

</details>
This commit is contained in:
aecsocket 2024-11-11 18:46:23 +00:00 committed by GitHub
parent c62c13dc2a
commit 57931ce42f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 775 additions and 197 deletions

View file

@ -5,31 +5,25 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{Error, SeqAccess, Visitor}; use serde::de::{Error, SeqAccess, Visitor};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`Array`] values. /// A [`Visitor`] for deserializing [`Array`] values.
/// ///
/// [`Array`]: crate::Array /// [`Array`]: crate::Array
pub(super) struct ArrayVisitor<'a> { pub(super) struct ArrayVisitor<'a, P> {
array_info: &'static ArrayInfo, pub array_info: &'static ArrayInfo,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> ArrayVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for ArrayVisitor<'_, P> {
pub fn new(array_info: &'static ArrayInfo, registry: &'a TypeRegistry) -> Self {
Self {
array_info,
registry,
}
}
}
impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> {
type Value = DynamicArray; type Value = DynamicArray;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("reflected array value") formatter.write_str("reflected array value")
} }
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error> fn visit_seq<V>(mut self, mut seq: V) -> Result<Self::Value, V::Error>
where where
V: SeqAccess<'de>, V: SeqAccess<'de>,
{ {
@ -38,6 +32,7 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> {
while let Some(value) = seq.next_element_seed(TypedReflectDeserializer::new_internal( while let Some(value) = seq.next_element_seed(TypedReflectDeserializer::new_internal(
registration, registration,
self.registry, self.registry,
self.processor.as_deref_mut(),
))? { ))? {
vec.push(value); vec.push(value);
} }

View file

@ -15,6 +15,8 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{DeserializeSeed, Error, IgnoredAny, MapAccess, Visitor}; use serde::de::{DeserializeSeed, Error, IgnoredAny, MapAccess, Visitor};
use super::ReflectDeserializerProcessor;
/// A general purpose deserializer for reflected types. /// A general purpose deserializer for reflected types.
/// ///
/// This is the deserializer counterpart to [`ReflectSerializer`]. /// This is the deserializer counterpart to [`ReflectSerializer`].
@ -42,6 +44,10 @@ use serde::de::{DeserializeSeed, Error, IgnoredAny, MapAccess, Visitor};
/// This means that if the actual type is needed, these dynamic representations will need to /// This means that if the actual type is needed, these dynamic representations will need to
/// be converted to the concrete type using [`FromReflect`] or [`ReflectFromReflect`]. /// be converted to the concrete type using [`FromReflect`] or [`ReflectFromReflect`].
/// ///
/// If you want to override deserialization for a specific [`TypeRegistration`],
/// you can pass in a reference to a [`ReflectDeserializerProcessor`] which will
/// take priority over all other deserialization methods - see [`with_processor`].
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -94,28 +100,57 @@ use serde::de::{DeserializeSeed, Error, IgnoredAny, MapAccess, Visitor};
/// [`Box<DynamicList>`]: crate::DynamicList /// [`Box<DynamicList>`]: crate::DynamicList
/// [`FromReflect`]: crate::FromReflect /// [`FromReflect`]: crate::FromReflect
/// [`ReflectFromReflect`]: crate::ReflectFromReflect /// [`ReflectFromReflect`]: crate::ReflectFromReflect
pub struct ReflectDeserializer<'a> { /// [`with_processor`]: Self::with_processor
pub struct ReflectDeserializer<'a, P: ReflectDeserializerProcessor = ()> {
registry: &'a TypeRegistry, registry: &'a TypeRegistry,
processor: Option<&'a mut P>,
} }
impl<'a> ReflectDeserializer<'a> { impl<'a> ReflectDeserializer<'a, ()> {
/// Creates a deserializer with no processor.
///
/// If you want to add custom logic for deserializing certain types, use
/// [`with_processor`].
///
/// [`with_processor`]: Self::with_processor
pub fn new(registry: &'a TypeRegistry) -> Self { pub fn new(registry: &'a TypeRegistry) -> Self {
Self { registry } Self {
registry,
processor: None,
}
} }
} }
impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { impl<'a, P: ReflectDeserializerProcessor> ReflectDeserializer<'a, P> {
/// Creates a deserializer with a processor.
///
/// If you do not need any custom logic for handling certain types, use
/// [`new`].
///
/// [`new`]: Self::new
pub fn with_processor(registry: &'a TypeRegistry, processor: &'a mut P) -> Self {
Self {
registry,
processor: Some(processor),
}
}
}
impl<'de, P: ReflectDeserializerProcessor> DeserializeSeed<'de> for ReflectDeserializer<'_, P> {
type Value = Box<dyn PartialReflect>; type Value = Box<dyn PartialReflect>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
struct UntypedReflectDeserializerVisitor<'a> { struct UntypedReflectDeserializerVisitor<'a, P> {
registry: &'a TypeRegistry, registry: &'a TypeRegistry,
processor: Option<&'a mut P>,
} }
impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de>
for UntypedReflectDeserializerVisitor<'_, P>
{
type Value = Box<dyn PartialReflect>; type Value = Box<dyn PartialReflect>;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
@ -131,10 +166,11 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> {
.next_key_seed(TypeRegistrationDeserializer::new(self.registry))? .next_key_seed(TypeRegistrationDeserializer::new(self.registry))?
.ok_or_else(|| Error::invalid_length(0, &"a single entry"))?; .ok_or_else(|| Error::invalid_length(0, &"a single entry"))?;
let value = map.next_value_seed(TypedReflectDeserializer { let value = map.next_value_seed(TypedReflectDeserializer::new_internal(
registration, registration,
registry: self.registry, self.registry,
})?; self.processor,
))?;
if map.next_key::<IgnoredAny>()?.is_some() { if map.next_key::<IgnoredAny>()?.is_some() {
return Err(Error::invalid_length(2, &"a single entry")); return Err(Error::invalid_length(2, &"a single entry"));
@ -146,6 +182,7 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> {
deserializer.deserialize_map(UntypedReflectDeserializerVisitor { deserializer.deserialize_map(UntypedReflectDeserializerVisitor {
registry: self.registry, registry: self.registry,
processor: self.processor,
}) })
} }
} }
@ -175,6 +212,10 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> {
/// This means that if the actual type is needed, these dynamic representations will need to /// This means that if the actual type is needed, these dynamic representations will need to
/// be converted to the concrete type using [`FromReflect`] or [`ReflectFromReflect`]. /// be converted to the concrete type using [`FromReflect`] or [`ReflectFromReflect`].
/// ///
/// If you want to override deserialization for a specific [`TypeRegistration`],
/// you can pass in a reference to a [`ReflectDeserializerProcessor`] which will
/// take priority over all other deserialization methods - see [`with_processor`].
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -226,13 +267,20 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> {
/// [`Box<DynamicList>`]: crate::DynamicList /// [`Box<DynamicList>`]: crate::DynamicList
/// [`FromReflect`]: crate::FromReflect /// [`FromReflect`]: crate::FromReflect
/// [`ReflectFromReflect`]: crate::ReflectFromReflect /// [`ReflectFromReflect`]: crate::ReflectFromReflect
pub struct TypedReflectDeserializer<'a> { /// [`with_processor`]: Self::with_processor
pub struct TypedReflectDeserializer<'a, P: ReflectDeserializerProcessor = ()> {
registration: &'a TypeRegistration, registration: &'a TypeRegistration,
registry: &'a TypeRegistry, registry: &'a TypeRegistry,
processor: Option<&'a mut P>,
} }
impl<'a> TypedReflectDeserializer<'a> { impl<'a> TypedReflectDeserializer<'a, ()> {
/// Creates a new [`TypedReflectDeserializer`] for the given type registration. /// Creates a typed deserializer with no processor.
///
/// If you want to add custom logic for deserializing certain types, use
/// [`with_processor`].
///
/// [`with_processor`]: Self::with_processor
pub fn new(registration: &'a TypeRegistration, registry: &'a TypeRegistry) -> Self { pub fn new(registration: &'a TypeRegistration, registry: &'a TypeRegistry) -> Self {
#[cfg(feature = "debug_stack")] #[cfg(feature = "debug_stack")]
TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new()); TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());
@ -240,10 +288,12 @@ impl<'a> TypedReflectDeserializer<'a> {
Self { Self {
registration, registration,
registry, registry,
processor: None,
} }
} }
/// Creates a new [`TypedReflectDeserializer`] for the given type `T`. /// Creates a new [`TypedReflectDeserializer`] for the given type `T`
/// without a processor.
/// ///
/// # Panics /// # Panics
/// ///
@ -256,6 +306,30 @@ impl<'a> TypedReflectDeserializer<'a> {
Self { Self {
registration, registration,
registry, registry,
processor: None,
}
}
}
impl<'a, P: ReflectDeserializerProcessor> TypedReflectDeserializer<'a, P> {
/// Creates a typed deserializer with a processor.
///
/// If you do not need any custom logic for handling certain types, use
/// [`new`].
///
/// [`new`]: Self::new
pub fn with_processor(
registration: &'a TypeRegistration,
registry: &'a TypeRegistry,
processor: &'a mut P,
) -> Self {
#[cfg(feature = "debug_stack")]
TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());
Self {
registration,
registry,
processor: Some(processor),
} }
} }
@ -263,22 +337,42 @@ impl<'a> TypedReflectDeserializer<'a> {
pub(super) fn new_internal( pub(super) fn new_internal(
registration: &'a TypeRegistration, registration: &'a TypeRegistration,
registry: &'a TypeRegistry, registry: &'a TypeRegistry,
processor: Option<&'a mut P>,
) -> Self { ) -> Self {
Self { Self {
registration, registration,
registry, registry,
processor,
} }
} }
} }
impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { impl<'de, P: ReflectDeserializerProcessor> DeserializeSeed<'de>
for TypedReflectDeserializer<'_, P>
{
type Value = Box<dyn PartialReflect>; type Value = Box<dyn PartialReflect>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> fn deserialize<D>(mut self, deserializer: D) -> Result<Self::Value, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
let deserialize_internal = || -> Result<Self::Value, D::Error> { let deserialize_internal = || -> Result<Self::Value, D::Error> {
// First, check if our processor wants to deserialize this type
// This takes priority over any other deserialization operations
let deserializer = if let Some(processor) = self.processor.as_deref_mut() {
match processor.try_deserialize(self.registration, self.registry, deserializer) {
Ok(Ok(value)) => {
return Ok(value);
}
Err(err) => {
return Err(make_custom_error(err));
}
Ok(Err(deserializer)) => deserializer,
}
} else {
deserializer
};
let type_path = self.registration.type_info().type_path(); let type_path = self.registration.type_info().type_path();
// Handle both Value case and types that have a custom `ReflectDeserialize` // Handle both Value case and types that have a custom `ReflectDeserialize`
@ -299,7 +393,12 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
let mut dynamic_struct = deserializer.deserialize_struct( let mut dynamic_struct = deserializer.deserialize_struct(
struct_info.type_path_table().ident().unwrap(), struct_info.type_path_table().ident().unwrap(),
struct_info.field_names(), struct_info.field_names(),
StructVisitor::new(struct_info, self.registration, self.registry), StructVisitor {
struct_info,
registration: self.registration,
registry: self.registry,
processor: self.processor,
},
)?; )?;
dynamic_struct.set_represented_type(Some(self.registration.type_info())); dynamic_struct.set_represented_type(Some(self.registration.type_info()));
Ok(Box::new(dynamic_struct)) Ok(Box::new(dynamic_struct))
@ -310,57 +409,76 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
{ {
deserializer.deserialize_newtype_struct( deserializer.deserialize_newtype_struct(
tuple_struct_info.type_path_table().ident().unwrap(), tuple_struct_info.type_path_table().ident().unwrap(),
TupleStructVisitor::new( TupleStructVisitor {
tuple_struct_info, tuple_struct_info,
self.registration, registration: self.registration,
self.registry, registry: self.registry,
), processor: self.processor,
},
)? )?
} else { } else {
deserializer.deserialize_tuple_struct( deserializer.deserialize_tuple_struct(
tuple_struct_info.type_path_table().ident().unwrap(), tuple_struct_info.type_path_table().ident().unwrap(),
tuple_struct_info.field_len(), tuple_struct_info.field_len(),
TupleStructVisitor::new( TupleStructVisitor {
tuple_struct_info, tuple_struct_info,
self.registration, registration: self.registration,
self.registry, registry: self.registry,
), processor: self.processor,
},
)? )?
}; };
dynamic_tuple_struct.set_represented_type(Some(self.registration.type_info())); dynamic_tuple_struct.set_represented_type(Some(self.registration.type_info()));
Ok(Box::new(dynamic_tuple_struct)) Ok(Box::new(dynamic_tuple_struct))
} }
TypeInfo::List(list_info) => { TypeInfo::List(list_info) => {
let mut dynamic_list = let mut dynamic_list = deserializer.deserialize_seq(ListVisitor {
deserializer.deserialize_seq(ListVisitor::new(list_info, self.registry))?; list_info,
registry: self.registry,
processor: self.processor,
})?;
dynamic_list.set_represented_type(Some(self.registration.type_info())); dynamic_list.set_represented_type(Some(self.registration.type_info()));
Ok(Box::new(dynamic_list)) Ok(Box::new(dynamic_list))
} }
TypeInfo::Array(array_info) => { TypeInfo::Array(array_info) => {
let mut dynamic_array = deserializer.deserialize_tuple( let mut dynamic_array = deserializer.deserialize_tuple(
array_info.capacity(), array_info.capacity(),
ArrayVisitor::new(array_info, self.registry), ArrayVisitor {
array_info,
registry: self.registry,
processor: self.processor,
},
)?; )?;
dynamic_array.set_represented_type(Some(self.registration.type_info())); dynamic_array.set_represented_type(Some(self.registration.type_info()));
Ok(Box::new(dynamic_array)) Ok(Box::new(dynamic_array))
} }
TypeInfo::Map(map_info) => { TypeInfo::Map(map_info) => {
let mut dynamic_map = let mut dynamic_map = deserializer.deserialize_map(MapVisitor {
deserializer.deserialize_map(MapVisitor::new(map_info, self.registry))?; map_info,
registry: self.registry,
processor: self.processor,
})?;
dynamic_map.set_represented_type(Some(self.registration.type_info())); dynamic_map.set_represented_type(Some(self.registration.type_info()));
Ok(Box::new(dynamic_map)) Ok(Box::new(dynamic_map))
} }
TypeInfo::Set(set_info) => { TypeInfo::Set(set_info) => {
let mut dynamic_set = let mut dynamic_set = deserializer.deserialize_seq(SetVisitor {
deserializer.deserialize_seq(SetVisitor::new(set_info, self.registry))?; set_info,
registry: self.registry,
processor: self.processor,
})?;
dynamic_set.set_represented_type(Some(self.registration.type_info())); dynamic_set.set_represented_type(Some(self.registration.type_info()));
Ok(Box::new(dynamic_set)) Ok(Box::new(dynamic_set))
} }
TypeInfo::Tuple(tuple_info) => { TypeInfo::Tuple(tuple_info) => {
let mut dynamic_tuple = deserializer.deserialize_tuple( let mut dynamic_tuple = deserializer.deserialize_tuple(
tuple_info.field_len(), tuple_info.field_len(),
TupleVisitor::new(tuple_info, self.registration, self.registry), TupleVisitor {
tuple_info,
registration: self.registration,
registry: self.registry,
processor: self.processor,
},
)?; )?;
dynamic_tuple.set_represented_type(Some(self.registration.type_info())); dynamic_tuple.set_represented_type(Some(self.registration.type_info()));
Ok(Box::new(dynamic_tuple)) Ok(Box::new(dynamic_tuple))
@ -370,13 +488,21 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
== Some("core::option") == Some("core::option")
&& enum_info.type_path_table().ident() == Some("Option") && enum_info.type_path_table().ident() == Some("Option")
{ {
deserializer deserializer.deserialize_option(OptionVisitor {
.deserialize_option(OptionVisitor::new(enum_info, self.registry))? enum_info,
registry: self.registry,
processor: self.processor,
})?
} else { } else {
deserializer.deserialize_enum( deserializer.deserialize_enum(
enum_info.type_path_table().ident().unwrap(), enum_info.type_path_table().ident().unwrap(),
enum_info.variant_names(), enum_info.variant_names(),
EnumVisitor::new(enum_info, self.registration, self.registry), EnumVisitor {
enum_info,
registration: self.registration,
registry: self.registry,
processor: self.processor,
},
)? )?
}; };
dynamic_enum.set_represented_type(Some(self.registration.type_info())); dynamic_enum.set_represented_type(Some(self.registration.type_info()));

View file

@ -15,30 +15,19 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor}; use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`Enum`] values. /// A [`Visitor`] for deserializing [`Enum`] values.
/// ///
/// [`Enum`]: crate::Enum /// [`Enum`]: crate::Enum
pub(super) struct EnumVisitor<'a> { pub(super) struct EnumVisitor<'a, P> {
enum_info: &'static EnumInfo, pub enum_info: &'static EnumInfo,
registration: &'a TypeRegistration, pub registration: &'a TypeRegistration,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> EnumVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for EnumVisitor<'_, P> {
pub fn new(
enum_info: &'static EnumInfo,
registration: &'a TypeRegistration,
registry: &'a TypeRegistry,
) -> Self {
Self {
enum_info,
registration,
registry,
}
}
}
impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
type Value = DynamicEnum; type Value = DynamicEnum;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
@ -63,6 +52,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
struct_info, struct_info,
registration: self.registration, registration: self.registration,
registry: self.registry, registry: self.registry,
processor: self.processor,
}, },
)? )?
.into(), .into(),
@ -71,9 +61,12 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
*TupleLikeInfo::field_at(tuple_info, 0)?.ty(), *TupleLikeInfo::field_at(tuple_info, 0)?.ty(),
self.registry, self.registry,
)?; )?;
let value = variant.newtype_variant_seed( let value =
TypedReflectDeserializer::new_internal(registration, self.registry), variant.newtype_variant_seed(TypedReflectDeserializer::new_internal(
)?; registration,
self.registry,
self.processor,
))?;
let mut dynamic_tuple = DynamicTuple::default(); let mut dynamic_tuple = DynamicTuple::default();
dynamic_tuple.insert_boxed(value); dynamic_tuple.insert_boxed(value);
dynamic_tuple.into() dynamic_tuple.into()
@ -85,6 +78,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
tuple_info, tuple_info,
registration: self.registration, registration: self.registration,
registry: self.registry, registry: self.registry,
processor: self.processor,
}, },
)? )?
.into(), .into(),
@ -151,13 +145,14 @@ impl<'de> DeserializeSeed<'de> for VariantDeserializer {
} }
} }
struct StructVariantVisitor<'a> { struct StructVariantVisitor<'a, P> {
struct_info: &'static StructVariantInfo, struct_info: &'static StructVariantInfo,
registration: &'a TypeRegistration, registration: &'a TypeRegistration,
registry: &'a TypeRegistry, registry: &'a TypeRegistry,
processor: Option<&'a mut P>,
} }
impl<'a, 'de> Visitor<'de> for StructVariantVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for StructVariantVisitor<'_, P> {
type Value = DynamicStruct; type Value = DynamicStruct;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
@ -168,24 +163,37 @@ impl<'a, 'de> Visitor<'de> for StructVariantVisitor<'a> {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
visit_struct_seq(&mut seq, self.struct_info, self.registration, self.registry) visit_struct_seq(
&mut seq,
self.struct_info,
self.registration,
self.registry,
self.processor,
)
} }
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where where
V: MapAccess<'de>, V: MapAccess<'de>,
{ {
visit_struct(&mut map, self.struct_info, self.registration, self.registry) visit_struct(
&mut map,
self.struct_info,
self.registration,
self.registry,
self.processor,
)
} }
} }
struct TupleVariantVisitor<'a> { struct TupleVariantVisitor<'a, P> {
tuple_info: &'static TupleVariantInfo, tuple_info: &'static TupleVariantInfo,
registration: &'a TypeRegistration, registration: &'a TypeRegistration,
registry: &'a TypeRegistry, registry: &'a TypeRegistry,
processor: Option<&'a mut P>,
} }
impl<'a, 'de> Visitor<'de> for TupleVariantVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for TupleVariantVisitor<'_, P> {
type Value = DynamicTuple; type Value = DynamicTuple;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
@ -196,6 +204,12 @@ impl<'a, 'de> Visitor<'de> for TupleVariantVisitor<'a> {
where where
V: SeqAccess<'de>, V: SeqAccess<'de>,
{ {
visit_tuple(&mut seq, self.tuple_info, self.registration, self.registry) visit_tuple(
&mut seq,
self.tuple_info,
self.registration,
self.registry,
self.processor,
)
} }
} }

View file

@ -5,31 +5,25 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{SeqAccess, Visitor}; use serde::de::{SeqAccess, Visitor};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`List`] values. /// A [`Visitor`] for deserializing [`List`] values.
/// ///
/// [`List`]: crate::List /// [`List`]: crate::List
pub(super) struct ListVisitor<'a> { pub(super) struct ListVisitor<'a, P> {
list_info: &'static ListInfo, pub list_info: &'static ListInfo,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> ListVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for ListVisitor<'_, P> {
pub fn new(list_info: &'static ListInfo, registry: &'a TypeRegistry) -> Self {
Self {
list_info,
registry,
}
}
}
impl<'a, 'de> Visitor<'de> for ListVisitor<'a> {
type Value = DynamicList; type Value = DynamicList;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("reflected list value") formatter.write_str("reflected list value")
} }
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error> fn visit_seq<V>(mut self, mut seq: V) -> Result<Self::Value, V::Error>
where where
V: SeqAccess<'de>, V: SeqAccess<'de>,
{ {
@ -38,6 +32,7 @@ impl<'a, 'de> Visitor<'de> for ListVisitor<'a> {
while let Some(value) = seq.next_element_seed(TypedReflectDeserializer::new_internal( while let Some(value) = seq.next_element_seed(TypedReflectDeserializer::new_internal(
registration, registration,
self.registry, self.registry,
self.processor.as_deref_mut(),
))? { ))? {
list.push_box(value); list.push_box(value);
} }

View file

@ -5,28 +5,25 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{MapAccess, Visitor}; use serde::de::{MapAccess, Visitor};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`Map`] values. /// A [`Visitor`] for deserializing [`Map`] values.
/// ///
/// [`Map`]: crate::Map /// [`Map`]: crate::Map
pub(super) struct MapVisitor<'a> { pub(super) struct MapVisitor<'a, P> {
map_info: &'static MapInfo, pub map_info: &'static MapInfo,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> MapVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for MapVisitor<'_, P> {
pub fn new(map_info: &'static MapInfo, registry: &'a TypeRegistry) -> Self {
Self { map_info, registry }
}
}
impl<'a, 'de> Visitor<'de> for MapVisitor<'a> {
type Value = DynamicMap; type Value = DynamicMap;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("reflected map value") formatter.write_str("reflected map value")
} }
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> fn visit_map<V>(mut self, mut map: V) -> Result<Self::Value, V::Error>
where where
V: MapAccess<'de>, V: MapAccess<'de>,
{ {
@ -36,10 +33,12 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> {
while let Some(key) = map.next_key_seed(TypedReflectDeserializer::new_internal( while let Some(key) = map.next_key_seed(TypedReflectDeserializer::new_internal(
key_registration, key_registration,
self.registry, self.registry,
self.processor.as_deref_mut(),
))? { ))? {
let value = map.next_value_seed(TypedReflectDeserializer::new_internal( let value = map.next_value_seed(TypedReflectDeserializer::new_internal(
value_registration, value_registration,
self.registry, self.registry,
self.processor.as_deref_mut(),
))?; ))?;
dynamic_map.insert_boxed(key, value); dynamic_map.insert_boxed(key, value);
} }

View file

@ -1,5 +1,6 @@
pub use deserialize_with_registry::*; pub use deserialize_with_registry::*;
pub use deserializer::*; pub use deserializer::*;
pub use processor::*;
pub use registrations::*; pub use registrations::*;
mod arrays; mod arrays;
@ -11,6 +12,7 @@ mod helpers;
mod lists; mod lists;
mod maps; mod maps;
mod options; mod options;
mod processor;
mod registration_utils; mod registration_utils;
mod registrations; mod registrations;
mod sets; mod sets;
@ -24,12 +26,15 @@ mod tuples;
mod tests { mod tests {
use bincode::Options; use bincode::Options;
use core::{any::TypeId, f32::consts::PI, ops::RangeInclusive}; use core::{any::TypeId, f32::consts::PI, ops::RangeInclusive};
use serde::de::IgnoredAny;
use serde::Deserializer;
use serde::{de::DeserializeSeed, Deserialize}; use serde::{de::DeserializeSeed, Deserialize};
use bevy_utils::{HashMap, HashSet}; use bevy_utils::{HashMap, HashSet};
use crate as bevy_reflect; use crate::serde::ReflectDeserializerProcessor;
use crate::{self as bevy_reflect, TypeRegistration};
use crate::{ use crate::{
serde::{ReflectDeserializer, ReflectSerializer, TypedReflectDeserializer}, serde::{ReflectDeserializer, ReflectSerializer, TypedReflectDeserializer},
DynamicEnum, FromReflect, PartialReflect, Reflect, ReflectDeserialize, TypeRegistry, DynamicEnum, FromReflect, PartialReflect, Reflect, ReflectDeserialize, TypeRegistry,
@ -275,15 +280,14 @@ mod tests {
let mut registry = get_registry(); let mut registry = get_registry();
registry.register::<Foo>(); registry.register::<Foo>();
let registration = registry.get(TypeId::of::<Foo>()).unwrap(); let registration = registry.get(TypeId::of::<Foo>()).unwrap();
let reflect_deserializer = TypedReflectDeserializer::new_internal(registration, &registry); let reflect_deserializer = TypedReflectDeserializer::new(registration, &registry);
let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap(); let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap();
let dynamic_output = reflect_deserializer let dynamic_output = reflect_deserializer
.deserialize(&mut ron_deserializer) .deserialize(&mut ron_deserializer)
.unwrap(); .unwrap();
let output = let output =
<Foo as FromReflect>::from_reflect(dynamic_output.as_ref().as_partial_reflect()) <Foo as FromReflect>::from_reflect(dynamic_output.as_partial_reflect()).unwrap();
.unwrap();
assert_eq!(expected, output); assert_eq!(expected, output);
} }
@ -517,6 +521,243 @@ mod tests {
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())); 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()));
} }
#[test]
fn should_use_processor_for_custom_deserialization() {
#[derive(Reflect, Debug, PartialEq)]
struct Foo {
bar: i32,
qux: i64,
}
struct FooProcessor;
impl ReflectDeserializerProcessor for FooProcessor {
fn try_deserialize<'de, D>(
&mut self,
registration: &TypeRegistration,
_: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
where
D: Deserializer<'de>,
{
if registration.type_id() == TypeId::of::<i64>() {
let _ = deserializer.deserialize_ignored_any(IgnoredAny);
Ok(Ok(Box::new(456_i64)))
} else {
Ok(Err(deserializer))
}
}
}
let expected = Foo { bar: 123, qux: 456 };
let input = r#"(
bar: 123,
qux: 123,
)"#;
let mut registry = get_registry();
registry.register::<Foo>();
let registration = registry.get(TypeId::of::<Foo>()).unwrap();
let mut processor = FooProcessor;
let reflect_deserializer =
TypedReflectDeserializer::with_processor(registration, &registry, &mut processor);
let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap();
let dynamic_output = reflect_deserializer
.deserialize(&mut ron_deserializer)
.unwrap();
let output =
<Foo as FromReflect>::from_reflect(dynamic_output.as_partial_reflect()).unwrap();
assert_eq!(expected, output);
}
#[test]
fn should_use_processor_for_multiple_registrations() {
#[derive(Reflect, Debug, PartialEq)]
struct Foo {
bar: i32,
qux: i64,
}
struct FooProcessor;
impl ReflectDeserializerProcessor for FooProcessor {
fn try_deserialize<'de, D>(
&mut self,
registration: &TypeRegistration,
_: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
where
D: Deserializer<'de>,
{
if registration.type_id() == TypeId::of::<i32>() {
let _ = deserializer.deserialize_ignored_any(IgnoredAny);
Ok(Ok(Box::new(123_i32)))
} else if registration.type_id() == TypeId::of::<i64>() {
let _ = deserializer.deserialize_ignored_any(IgnoredAny);
Ok(Ok(Box::new(456_i64)))
} else {
Ok(Err(deserializer))
}
}
}
let expected = Foo { bar: 123, qux: 456 };
let input = r#"(
bar: 0,
qux: 0,
)"#;
let mut registry = get_registry();
registry.register::<Foo>();
let registration = registry.get(TypeId::of::<Foo>()).unwrap();
let mut processor = FooProcessor;
let reflect_deserializer =
TypedReflectDeserializer::with_processor(registration, &registry, &mut processor);
let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap();
let dynamic_output = reflect_deserializer
.deserialize(&mut ron_deserializer)
.unwrap();
let output =
<Foo as FromReflect>::from_reflect(dynamic_output.as_partial_reflect()).unwrap();
assert_eq!(expected, output);
}
#[test]
fn should_propagate_processor_deserialize_error() {
struct ErroringProcessor;
impl ReflectDeserializerProcessor for ErroringProcessor {
fn try_deserialize<'de, D>(
&mut self,
registration: &TypeRegistration,
_: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
where
D: Deserializer<'de>,
{
if registration.type_id() == TypeId::of::<i32>() {
Err(serde::de::Error::custom("my custom deserialize error"))
} else {
Ok(Err(deserializer))
}
}
}
let registry = get_registry();
let input = r#"{"i32":123}"#;
let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
let mut processor = ErroringProcessor;
let reflect_deserializer = ReflectDeserializer::with_processor(&registry, &mut processor);
let error = reflect_deserializer
.deserialize(&mut deserializer)
.unwrap_err();
#[cfg(feature = "debug_stack")]
assert_eq!(
error,
ron::Error::Message("my custom deserialize error (stack: `i32`)".to_string())
);
#[cfg(not(feature = "debug_stack"))]
assert_eq!(
error,
ron::Error::Message("my custom deserialize error".to_string())
);
}
#[test]
fn should_access_local_scope_in_processor() {
struct ValueCountingProcessor<'a> {
values_found: &'a mut usize,
}
impl ReflectDeserializerProcessor for ValueCountingProcessor<'_> {
fn try_deserialize<'de, D>(
&mut self,
_: &TypeRegistration,
_: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
where
D: Deserializer<'de>,
{
let _ = deserializer.deserialize_ignored_any(IgnoredAny)?;
*self.values_found += 1;
Ok(Ok(Box::new(123_i32)))
}
}
let registry = get_registry();
let input = r#"{"i32":0}"#;
let mut values_found = 0_usize;
let mut deserializer_processor = ValueCountingProcessor {
values_found: &mut values_found,
};
let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
let reflect_deserializer =
ReflectDeserializer::with_processor(&registry, &mut deserializer_processor);
reflect_deserializer.deserialize(&mut deserializer).unwrap();
assert_eq!(1, values_found);
}
#[test]
fn should_fail_from_reflect_if_processor_returns_wrong_typed_value() {
#[derive(Reflect, Debug, PartialEq)]
struct Foo {
bar: i32,
qux: i64,
}
struct WrongTypeProcessor;
impl ReflectDeserializerProcessor for WrongTypeProcessor {
fn try_deserialize<'de, D>(
&mut self,
registration: &TypeRegistration,
_registry: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
where
D: Deserializer<'de>,
{
if registration.type_id() == TypeId::of::<i32>() {
let _ = deserializer.deserialize_ignored_any(IgnoredAny);
Ok(Ok(Box::new(42_i64)))
} else {
Ok(Err(deserializer))
}
}
}
let input = r#"(
bar: 123,
qux: 123,
)"#;
let mut registry = get_registry();
registry.register::<Foo>();
let registration = registry.get(TypeId::of::<Foo>()).unwrap();
let mut processor = WrongTypeProcessor;
let reflect_deserializer =
TypedReflectDeserializer::with_processor(registration, &registry, &mut processor);
let mut ron_deserializer = ron::de::Deserializer::from_str(input).unwrap();
let dynamic_output = reflect_deserializer
.deserialize(&mut ron_deserializer)
.unwrap();
assert!(<Foo as FromReflect>::from_reflect(dynamic_output.as_partial_reflect()).is_none());
}
#[cfg(feature = "functions")] #[cfg(feature = "functions")]
mod functions { mod functions {
use super::*; use super::*;

View file

@ -8,22 +8,16 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{DeserializeSeed, Error, Visitor}; use serde::de::{DeserializeSeed, Error, Visitor};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`Option`] values. /// A [`Visitor`] for deserializing [`Option`] values.
pub(super) struct OptionVisitor<'a> { pub(super) struct OptionVisitor<'a, P> {
enum_info: &'static EnumInfo, pub enum_info: &'static EnumInfo,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> OptionVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for OptionVisitor<'_, P> {
pub fn new(enum_info: &'static EnumInfo, registry: &'a TypeRegistry) -> Self {
Self {
enum_info,
registry,
}
}
}
impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> {
type Value = DynamicEnum; type Value = DynamicEnum;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
@ -49,7 +43,11 @@ impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> {
VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => {
let field = tuple_info.field_at(0).unwrap(); let field = tuple_info.field_at(0).unwrap();
let registration = try_get_registration(*field.ty(), self.registry)?; let registration = try_get_registration(*field.ty(), self.registry)?;
let de = TypedReflectDeserializer::new_internal(registration, self.registry); let de = TypedReflectDeserializer::new_internal(
registration,
self.registry,
self.processor,
);
let mut value = DynamicTuple::default(); let mut value = DynamicTuple::default();
value.insert_boxed(de.deserialize(deserializer)?); value.insert_boxed(de.deserialize(deserializer)?);
let mut option = DynamicEnum::default(); let mut option = DynamicEnum::default();

View file

@ -0,0 +1,213 @@
use crate::{PartialReflect, TypeRegistration, TypeRegistry};
/// Allows overriding the default deserialization behavior of
/// [`ReflectDeserializer`] and [`TypedReflectDeserializer`] for specific
/// [`TypeRegistration`]s.
///
/// When deserializing a reflected value, you may want to override the default
/// behavior and use your own logic for deserialization. This logic may also
/// be context-dependent, and only apply for a single use of your
/// [`ReflectDeserializer`]. To achieve this, you can create a processor and
/// pass it in to your deserializer.
///
/// Whenever the deserializer attempts to deserialize a value, it will first
/// call [`try_deserialize`] on your processor, which may take ownership of the
/// deserializer and give back a [`Box<dyn PartialReflect>`], or return
/// ownership of the deserializer back, and continue with the default logic.
///
/// # Compared to [`DeserializeWithRegistry`]
///
/// [`DeserializeWithRegistry`] allows you to define how your type will be
/// deserialized by a [`TypedReflectDeserializer`], given the extra context of
/// the [`TypeRegistry`]. If your type can be deserialized entirely from that,
/// then you should prefer implementing that trait instead of using a processor.
///
/// However, you may need more context-dependent data which is only present in
/// the scope where you create the [`TypedReflectDeserializer`]. For example, in
/// an asset loader, the `&mut LoadContext` you get is only valid from within
/// the `load` function. This is where a processor is useful, as the processor
/// can capture local variables.
///
/// A [`ReflectDeserializerProcessor`] always takes priority over a
/// [`DeserializeWithRegistry`] implementation, so this is also useful for
/// overriding deserialization behavior if you need to do something custom.
///
/// # Examples
///
/// Deserializing a reflected value in an asset loader, and replacing asset
/// handles with a loaded equivalent:
///
/// ```
/// # use bevy_reflect::serde::{ReflectDeserializer, ReflectDeserializerProcessor};
/// # use bevy_reflect::{PartialReflect, Reflect, TypeData, TypeRegistration, TypeRegistry};
/// # use serde::de::{DeserializeSeed, Deserializer, Visitor};
/// # use std::marker::PhantomData;
/// #
/// # #[derive(Debug, Clone, Reflect)]
/// # struct LoadedUntypedAsset;
/// # #[derive(Debug, Clone, Reflect)]
/// # struct Handle<T: Reflect>(T);
/// # #[derive(Debug, Clone, Reflect)]
/// # struct Mesh;
/// #
/// # struct LoadContext;
/// # impl LoadContext {
/// # fn load(&mut self) -> &mut Self { unimplemented!() }
/// # fn with_asset_type_id(&mut self, (): ()) -> &mut Self { unimplemented!() }
/// # fn untyped(&mut self) -> &mut Self { unimplemented!() }
/// # fn load_asset(&mut self, (): ()) -> Handle<LoadedUntypedAsset> { unimplemented!() }
/// # }
/// #
/// # struct ReflectHandle;
/// # impl TypeData for ReflectHandle {
/// # fn clone_type_data(&self) -> Box<dyn TypeData> {
/// # unimplemented!()
/// # }
/// # }
/// # impl ReflectHandle {
/// # fn asset_type_id(&self) {
/// # unimplemented!()
/// # }
/// # }
/// #
/// # struct AssetPathVisitor;
/// # impl<'de> Visitor<'de> for AssetPathVisitor {
/// # type Value = ();
/// # fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { unimplemented!() }
/// # }
/// # type AssetError = Box<dyn core::error::Error>;
/// #[derive(Debug, Clone, Reflect)]
/// struct MyAsset {
/// name: String,
/// mesh: Handle<Mesh>,
/// }
///
/// fn load(
/// asset_bytes: &[u8],
/// type_registry: &TypeRegistry,
/// load_context: &mut LoadContext,
/// ) -> Result<MyAsset, AssetError> {
/// struct HandleProcessor<'a> {
/// load_context: &'a mut LoadContext,
/// }
///
/// impl ReflectDeserializerProcessor for HandleProcessor<'_> {
/// fn try_deserialize<'de, D>(
/// &mut self,
/// registration: &TypeRegistration,
/// _registry: &TypeRegistry,
/// deserializer: D,
/// ) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
/// where
/// D: Deserializer<'de>,
/// {
/// let Some(reflect_handle) = registration.data::<ReflectHandle>() else {
/// // we don't want to deserialize this - give the deserializer back
/// return Ok(Err(deserializer));
/// };
///
/// let asset_type_id = reflect_handle.asset_type_id();
/// let asset_path = deserializer.deserialize_str(AssetPathVisitor)?;
///
/// let handle: Handle<LoadedUntypedAsset> = self.load_context
/// .load()
/// .with_asset_type_id(asset_type_id)
/// .untyped()
/// .load_asset(asset_path);
/// # let _: Result<_, ()> = {
/// Ok(Box::new(handle))
/// # };
/// # unimplemented!()
/// }
/// }
///
/// let mut ron_deserializer = ron::Deserializer::from_bytes(asset_bytes)?;
/// let mut processor = HandleProcessor { load_context };
/// let reflect_deserializer =
/// ReflectDeserializer::with_processor(type_registry, &mut processor);
/// let asset = reflect_deserializer.deserialize(&mut ron_deserializer)?;
/// # unimplemented!()
/// }
/// ```
///
/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
/// [`try_deserialize`]: Self::try_deserialize
/// [`DeserializeWithRegistry`]: crate::serde::DeserializeWithRegistry
pub trait ReflectDeserializerProcessor {
/// Attempts to deserialize the value which a [`TypedReflectDeserializer`]
/// is currently looking at, and knows the type of.
///
/// If you've read the `registration` and want to override the default
/// deserialization, return `Ok(Ok(value))` with the boxed reflected value
/// that you want to assign this value to. The type inside the box must
/// be the same one as the `registration` is for, otherwise future
/// reflection operations (such as using [`FromReflect`] to convert the
/// resulting [`Box<dyn PartialReflect>`] into a concrete type) will fail.
///
/// If you don't want to override the deserialization, return ownership of
/// the deserializer back via `Ok(Err(deserializer))`.
///
/// Note that, if you do want to return a value, you *must* read from the
/// deserializer passed to this function (you are free to ignore the result
/// though). Otherwise, the deserializer will be in an inconsistent state,
/// and future value parsing will fail.
///
/// # Examples
///
/// Correct way to return a constant value (not using any output from the
/// deserializer):
///
/// ```
/// # use bevy_reflect::{TypeRegistration, PartialReflect, TypeRegistry};
/// # use bevy_reflect::serde::ReflectDeserializerProcessor;
/// # use core::any::TypeId;
/// use serde::de::IgnoredAny;
///
/// struct ConstantI32Processor;
///
/// impl ReflectDeserializerProcessor for ConstantI32Processor {
/// fn try_deserialize<'de, D>(
/// &mut self,
/// registration: &TypeRegistration,
/// _registry: &TypeRegistry,
/// deserializer: D,
/// ) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
/// where
/// D: serde::Deserializer<'de>
/// {
/// if registration.type_id() == TypeId::of::<i32>() {
/// _ = deserializer.deserialize_ignored_any(IgnoredAny);
/// Ok(Ok(Box::new(42_i32)))
/// } else {
/// Ok(Err(deserializer))
/// }
/// }
/// }
/// ```
///
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
/// [`FromReflect`]: crate::FromReflect
fn try_deserialize<'de, D>(
&mut self,
registration: &TypeRegistration,
registry: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
where
D: serde::Deserializer<'de>;
}
impl ReflectDeserializerProcessor for () {
fn try_deserialize<'de, D>(
&mut self,
_registration: &TypeRegistration,
_registry: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Err(deserializer))
}
}

View file

@ -5,28 +5,25 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{SeqAccess, Visitor}; use serde::de::{SeqAccess, Visitor};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`Set`] values. /// A [`Visitor`] for deserializing [`Set`] values.
/// ///
/// [`Set`]: crate::Set /// [`Set`]: crate::Set
pub(super) struct SetVisitor<'a> { pub(super) struct SetVisitor<'a, P> {
set_info: &'static SetInfo, pub set_info: &'static SetInfo,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> SetVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for SetVisitor<'_, P> {
pub fn new(set_info: &'static SetInfo, registry: &'a TypeRegistry) -> Self {
Self { set_info, registry }
}
}
impl<'a, 'de> Visitor<'de> for SetVisitor<'a> {
type Value = DynamicSet; type Value = DynamicSet;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("reflected set value") formatter.write_str("reflected set value")
} }
fn visit_seq<V>(self, mut set: V) -> Result<Self::Value, V::Error> fn visit_seq<V>(mut self, mut set: V) -> Result<Self::Value, V::Error>
where where
V: SeqAccess<'de>, V: SeqAccess<'de>,
{ {
@ -35,6 +32,7 @@ impl<'a, 'de> Visitor<'de> for SetVisitor<'a> {
while let Some(value) = set.next_element_seed(TypedReflectDeserializer::new_internal( while let Some(value) = set.next_element_seed(TypedReflectDeserializer::new_internal(
value_registration, value_registration,
self.registry, self.registry,
self.processor.as_deref_mut(),
))? { ))? {
dynamic_set.insert_boxed(value); dynamic_set.insert_boxed(value);
} }

View file

@ -12,6 +12,8 @@ use crate::{
use core::slice::Iter; use core::slice::Iter;
use serde::de::{Error, MapAccess, SeqAccess}; use serde::de::{Error, MapAccess, SeqAccess};
use super::ReflectDeserializerProcessor;
/// A helper trait for accessing type information from struct-like types. /// A helper trait for accessing type information from struct-like types.
pub(super) trait StructLikeInfo { pub(super) trait StructLikeInfo {
fn field<E: Error>(&self, name: &str) -> Result<&NamedField, E>; fn field<E: Error>(&self, name: &str) -> Result<&NamedField, E>;
@ -83,15 +85,17 @@ impl StructLikeInfo for StructVariantInfo {
/// Deserializes a [struct-like] type from a mapping of fields, returning a [`DynamicStruct`]. /// Deserializes a [struct-like] type from a mapping of fields, returning a [`DynamicStruct`].
/// ///
/// [struct-like]: StructLikeInfo /// [struct-like]: StructLikeInfo
pub(super) fn visit_struct<'de, T, V>( pub(super) fn visit_struct<'de, T, V, P>(
map: &mut V, map: &mut V,
info: &'static T, info: &'static T,
registration: &TypeRegistration, registration: &TypeRegistration,
registry: &TypeRegistry, registry: &TypeRegistry,
mut processor: Option<&mut P>,
) -> Result<DynamicStruct, V::Error> ) -> Result<DynamicStruct, V::Error>
where where
T: StructLikeInfo, T: StructLikeInfo,
V: MapAccess<'de>, V: MapAccess<'de>,
P: ReflectDeserializerProcessor,
{ {
let mut dynamic_struct = DynamicStruct::default(); let mut dynamic_struct = DynamicStruct::default();
while let Some(Ident(key)) = map.next_key::<Ident>()? { while let Some(Ident(key)) = map.next_key::<Ident>()? {
@ -107,6 +111,7 @@ where
let value = map.next_value_seed(TypedReflectDeserializer::new_internal( let value = map.next_value_seed(TypedReflectDeserializer::new_internal(
registration, registration,
registry, registry,
processor.as_deref_mut(),
))?; ))?;
dynamic_struct.insert_boxed(&key, value); dynamic_struct.insert_boxed(&key, value);
} }
@ -129,15 +134,17 @@ where
/// Deserializes a [struct-like] type from a sequence of fields, returning a [`DynamicStruct`]. /// Deserializes a [struct-like] type from a sequence of fields, returning a [`DynamicStruct`].
/// ///
/// [struct-like]: StructLikeInfo /// [struct-like]: StructLikeInfo
pub(super) fn visit_struct_seq<'de, T, V>( pub(super) fn visit_struct_seq<'de, T, V, P>(
seq: &mut V, seq: &mut V,
info: &T, info: &T,
registration: &TypeRegistration, registration: &TypeRegistration,
registry: &TypeRegistry, registry: &TypeRegistry,
mut processor: Option<&mut P>,
) -> Result<DynamicStruct, V::Error> ) -> Result<DynamicStruct, V::Error>
where where
T: StructLikeInfo, T: StructLikeInfo,
V: SeqAccess<'de>, V: SeqAccess<'de>,
P: ReflectDeserializerProcessor,
{ {
let mut dynamic_struct = DynamicStruct::default(); let mut dynamic_struct = DynamicStruct::default();
@ -167,6 +174,7 @@ where
.next_element_seed(TypedReflectDeserializer::new_internal( .next_element_seed(TypedReflectDeserializer::new_internal(
try_get_registration(*info.field_at(index)?.ty(), registry)?, try_get_registration(*info.field_at(index)?.ty(), registry)?,
registry, registry,
processor.as_deref_mut(),
))? ))?
.ok_or_else(|| Error::invalid_length(index, &len.to_string().as_str()))?; .ok_or_else(|| Error::invalid_length(index, &len.to_string().as_str()))?;
dynamic_struct.insert_boxed(name, value); dynamic_struct.insert_boxed(name, value);

View file

@ -5,30 +5,19 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{MapAccess, SeqAccess, Visitor}; use serde::de::{MapAccess, SeqAccess, Visitor};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`Struct`] values. /// A [`Visitor`] for deserializing [`Struct`] values.
/// ///
/// [`Struct`]: crate::Struct /// [`Struct`]: crate::Struct
pub(super) struct StructVisitor<'a> { pub(super) struct StructVisitor<'a, P> {
struct_info: &'static StructInfo, pub struct_info: &'static StructInfo,
registration: &'a TypeRegistration, pub registration: &'a TypeRegistration,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> StructVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for StructVisitor<'_, P> {
pub fn new(
struct_info: &'static StructInfo,
registration: &'a TypeRegistration,
registry: &'a TypeRegistry,
) -> Self {
Self {
struct_info,
registration,
registry,
}
}
}
impl<'a, 'de> Visitor<'de> for StructVisitor<'a> {
type Value = DynamicStruct; type Value = DynamicStruct;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
@ -39,13 +28,25 @@ impl<'a, 'de> Visitor<'de> for StructVisitor<'a> {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
visit_struct_seq(&mut seq, self.struct_info, self.registration, self.registry) visit_struct_seq(
&mut seq,
self.struct_info,
self.registration,
self.registry,
self.processor,
)
} }
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where where
V: MapAccess<'de>, V: MapAccess<'de>,
{ {
visit_struct(&mut map, self.struct_info, self.registration, self.registry) visit_struct(
&mut map,
self.struct_info,
self.registration,
self.registry,
self.processor,
)
} }
} }

View file

@ -7,30 +7,19 @@ use serde::de::{DeserializeSeed, SeqAccess, Visitor};
use super::{registration_utils::try_get_registration, TypedReflectDeserializer}; use super::{registration_utils::try_get_registration, TypedReflectDeserializer};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`TupleStruct`] values. /// A [`Visitor`] for deserializing [`TupleStruct`] values.
/// ///
/// [`TupleStruct`]: crate::TupleStruct /// [`TupleStruct`]: crate::TupleStruct
pub(super) struct TupleStructVisitor<'a> { pub(super) struct TupleStructVisitor<'a, P> {
tuple_struct_info: &'static TupleStructInfo, pub tuple_struct_info: &'static TupleStructInfo,
registration: &'a TypeRegistration, pub registration: &'a TypeRegistration,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> TupleStructVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for TupleStructVisitor<'_, P> {
pub fn new(
tuple_struct_info: &'static TupleStructInfo,
registration: &'a TypeRegistration,
registry: &'a TypeRegistry,
) -> Self {
Self {
tuple_struct_info,
registration,
registry,
}
}
}
impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> {
type Value = DynamicTupleStruct; type Value = DynamicTupleStruct;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
@ -46,6 +35,7 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> {
self.tuple_struct_info, self.tuple_struct_info,
self.registration, self.registration,
self.registry, self.registry,
self.processor,
) )
.map(DynamicTupleStruct::from) .map(DynamicTupleStruct::from)
} }
@ -71,7 +61,7 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> {
self.registry, self.registry,
)?; )?;
let reflect_deserializer = let reflect_deserializer =
TypedReflectDeserializer::new_internal(registration, self.registry); TypedReflectDeserializer::new_internal(registration, self.registry, self.processor);
let value = reflect_deserializer.deserialize(deserializer)?; let value = reflect_deserializer.deserialize(deserializer)?;
tuple.insert_boxed(value.into_partial_reflect()); tuple.insert_boxed(value.into_partial_reflect());

View file

@ -8,6 +8,8 @@ use crate::{
}; };
use serde::de::{Error, SeqAccess}; use serde::de::{Error, SeqAccess};
use super::ReflectDeserializerProcessor;
pub(super) trait TupleLikeInfo { pub(super) trait TupleLikeInfo {
fn field_at<E: Error>(&self, index: usize) -> Result<&UnnamedField, E>; fn field_at<E: Error>(&self, index: usize) -> Result<&UnnamedField, E>;
fn field_len(&self) -> usize; fn field_len(&self) -> usize;
@ -64,15 +66,17 @@ impl TupleLikeInfo for TupleVariantInfo {
/// Deserializes a [tuple-like] type from a sequence of elements, returning a [`DynamicTuple`]. /// Deserializes a [tuple-like] type from a sequence of elements, returning a [`DynamicTuple`].
/// ///
/// [tuple-like]: TupleLikeInfo /// [tuple-like]: TupleLikeInfo
pub(super) fn visit_tuple<'de, T, V>( pub(super) fn visit_tuple<'de, T, V, P>(
seq: &mut V, seq: &mut V,
info: &T, info: &T,
registration: &TypeRegistration, registration: &TypeRegistration,
registry: &TypeRegistry, registry: &TypeRegistry,
mut processor: Option<&mut P>,
) -> Result<DynamicTuple, V::Error> ) -> Result<DynamicTuple, V::Error>
where where
T: TupleLikeInfo, T: TupleLikeInfo,
V: SeqAccess<'de>, V: SeqAccess<'de>,
P: ReflectDeserializerProcessor,
{ {
let mut tuple = DynamicTuple::default(); let mut tuple = DynamicTuple::default();
@ -95,6 +99,7 @@ where
.next_element_seed(TypedReflectDeserializer::new_internal( .next_element_seed(TypedReflectDeserializer::new_internal(
try_get_registration(*info.field_at(index)?.ty(), registry)?, try_get_registration(*info.field_at(index)?.ty(), registry)?,
registry, registry,
processor.as_deref_mut(),
))? ))?
.ok_or_else(|| Error::invalid_length(index, &len.to_string().as_str()))?; .ok_or_else(|| Error::invalid_length(index, &len.to_string().as_str()))?;
tuple.insert_boxed(value); tuple.insert_boxed(value);

View file

@ -4,30 +4,19 @@ use crate::{
use core::{fmt, fmt::Formatter}; use core::{fmt, fmt::Formatter};
use serde::de::{SeqAccess, Visitor}; use serde::de::{SeqAccess, Visitor};
use super::ReflectDeserializerProcessor;
/// A [`Visitor`] for deserializing [`Tuple`] values. /// A [`Visitor`] for deserializing [`Tuple`] values.
/// ///
/// [`Tuple`]: crate::Tuple /// [`Tuple`]: crate::Tuple
pub(super) struct TupleVisitor<'a> { pub(super) struct TupleVisitor<'a, P> {
tuple_info: &'static TupleInfo, pub tuple_info: &'static TupleInfo,
registration: &'a TypeRegistration, pub registration: &'a TypeRegistration,
registry: &'a TypeRegistry, pub registry: &'a TypeRegistry,
pub processor: Option<&'a mut P>,
} }
impl<'a> TupleVisitor<'a> { impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for TupleVisitor<'_, P> {
pub fn new(
tuple_info: &'static TupleInfo,
registration: &'a TypeRegistration,
registry: &'a TypeRegistry,
) -> Self {
Self {
tuple_info,
registration,
registry,
}
}
}
impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> {
type Value = DynamicTuple; type Value = DynamicTuple;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
@ -38,6 +27,12 @@ impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> {
where where
V: SeqAccess<'de>, V: SeqAccess<'de>,
{ {
visit_tuple(&mut seq, self.tuple_info, self.registration, self.registry) visit_tuple(
&mut seq,
self.tuple_info,
self.registration,
self.registry,
self.processor,
)
} }
} }