mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 12:13:25 +00:00
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:
parent
c62c13dc2a
commit
57931ce42f
14 changed files with 775 additions and 197 deletions
|
@ -5,31 +5,25 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{Error, SeqAccess, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`Array`] values.
|
||||
///
|
||||
/// [`Array`]: crate::Array
|
||||
pub(super) struct ArrayVisitor<'a> {
|
||||
array_info: &'static ArrayInfo,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct ArrayVisitor<'a, P> {
|
||||
pub array_info: &'static ArrayInfo,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> ArrayVisitor<'a> {
|
||||
pub fn new(array_info: &'static ArrayInfo, registry: &'a TypeRegistry) -> Self {
|
||||
Self {
|
||||
array_info,
|
||||
registry,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for ArrayVisitor<'_, P> {
|
||||
type Value = DynamicArray;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
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
|
||||
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(
|
||||
registration,
|
||||
self.registry,
|
||||
self.processor.as_deref_mut(),
|
||||
))? {
|
||||
vec.push(value);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{DeserializeSeed, Error, IgnoredAny, MapAccess, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A general purpose deserializer for reflected types.
|
||||
///
|
||||
/// 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
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
|
@ -94,28 +100,57 @@ use serde::de::{DeserializeSeed, Error, IgnoredAny, MapAccess, Visitor};
|
|||
/// [`Box<DynamicList>`]: crate::DynamicList
|
||||
/// [`FromReflect`]: crate::FromReflect
|
||||
/// [`ReflectFromReflect`]: crate::ReflectFromReflect
|
||||
pub struct ReflectDeserializer<'a> {
|
||||
/// [`with_processor`]: Self::with_processor
|
||||
pub struct ReflectDeserializer<'a, P: ReflectDeserializerProcessor = ()> {
|
||||
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 {
|
||||
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>;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
struct UntypedReflectDeserializerVisitor<'a> {
|
||||
struct UntypedReflectDeserializerVisitor<'a, P> {
|
||||
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>;
|
||||
|
||||
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))?
|
||||
.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,
|
||||
registry: self.registry,
|
||||
})?;
|
||||
self.registry,
|
||||
self.processor,
|
||||
))?;
|
||||
|
||||
if map.next_key::<IgnoredAny>()?.is_some() {
|
||||
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 {
|
||||
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
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
|
@ -226,13 +267,20 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> {
|
|||
/// [`Box<DynamicList>`]: crate::DynamicList
|
||||
/// [`FromReflect`]: crate::FromReflect
|
||||
/// [`ReflectFromReflect`]: crate::ReflectFromReflect
|
||||
pub struct TypedReflectDeserializer<'a> {
|
||||
/// [`with_processor`]: Self::with_processor
|
||||
pub struct TypedReflectDeserializer<'a, P: ReflectDeserializerProcessor = ()> {
|
||||
registration: &'a TypeRegistration,
|
||||
registry: &'a TypeRegistry,
|
||||
processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> TypedReflectDeserializer<'a> {
|
||||
/// Creates a new [`TypedReflectDeserializer`] for the given type registration.
|
||||
impl<'a> TypedReflectDeserializer<'a, ()> {
|
||||
/// 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 {
|
||||
#[cfg(feature = "debug_stack")]
|
||||
TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());
|
||||
|
@ -240,10 +288,12 @@ impl<'a> TypedReflectDeserializer<'a> {
|
|||
Self {
|
||||
registration,
|
||||
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
|
||||
///
|
||||
|
@ -256,6 +306,30 @@ impl<'a> TypedReflectDeserializer<'a> {
|
|||
Self {
|
||||
registration,
|
||||
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(
|
||||
registration: &'a TypeRegistration,
|
||||
registry: &'a TypeRegistry,
|
||||
processor: Option<&'a mut P>,
|
||||
) -> Self {
|
||||
Self {
|
||||
registration,
|
||||
registry,
|
||||
processor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> DeserializeSeed<'de>
|
||||
for TypedReflectDeserializer<'_, P>
|
||||
{
|
||||
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
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
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();
|
||||
|
||||
// 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(
|
||||
struct_info.type_path_table().ident().unwrap(),
|
||||
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()));
|
||||
Ok(Box::new(dynamic_struct))
|
||||
|
@ -310,57 +409,76 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
|
|||
{
|
||||
deserializer.deserialize_newtype_struct(
|
||||
tuple_struct_info.type_path_table().ident().unwrap(),
|
||||
TupleStructVisitor::new(
|
||||
TupleStructVisitor {
|
||||
tuple_struct_info,
|
||||
self.registration,
|
||||
self.registry,
|
||||
),
|
||||
registration: self.registration,
|
||||
registry: self.registry,
|
||||
processor: self.processor,
|
||||
},
|
||||
)?
|
||||
} else {
|
||||
deserializer.deserialize_tuple_struct(
|
||||
tuple_struct_info.type_path_table().ident().unwrap(),
|
||||
tuple_struct_info.field_len(),
|
||||
TupleStructVisitor::new(
|
||||
TupleStructVisitor {
|
||||
tuple_struct_info,
|
||||
self.registration,
|
||||
self.registry,
|
||||
),
|
||||
registration: self.registration,
|
||||
registry: self.registry,
|
||||
processor: self.processor,
|
||||
},
|
||||
)?
|
||||
};
|
||||
|
||||
dynamic_tuple_struct.set_represented_type(Some(self.registration.type_info()));
|
||||
Ok(Box::new(dynamic_tuple_struct))
|
||||
}
|
||||
TypeInfo::List(list_info) => {
|
||||
let mut dynamic_list =
|
||||
deserializer.deserialize_seq(ListVisitor::new(list_info, self.registry))?;
|
||||
let mut dynamic_list = deserializer.deserialize_seq(ListVisitor {
|
||||
list_info,
|
||||
registry: self.registry,
|
||||
processor: self.processor,
|
||||
})?;
|
||||
dynamic_list.set_represented_type(Some(self.registration.type_info()));
|
||||
Ok(Box::new(dynamic_list))
|
||||
}
|
||||
TypeInfo::Array(array_info) => {
|
||||
let mut dynamic_array = deserializer.deserialize_tuple(
|
||||
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()));
|
||||
Ok(Box::new(dynamic_array))
|
||||
}
|
||||
TypeInfo::Map(map_info) => {
|
||||
let mut dynamic_map =
|
||||
deserializer.deserialize_map(MapVisitor::new(map_info, self.registry))?;
|
||||
let mut dynamic_map = deserializer.deserialize_map(MapVisitor {
|
||||
map_info,
|
||||
registry: self.registry,
|
||||
processor: self.processor,
|
||||
})?;
|
||||
dynamic_map.set_represented_type(Some(self.registration.type_info()));
|
||||
Ok(Box::new(dynamic_map))
|
||||
}
|
||||
TypeInfo::Set(set_info) => {
|
||||
let mut dynamic_set =
|
||||
deserializer.deserialize_seq(SetVisitor::new(set_info, self.registry))?;
|
||||
let mut dynamic_set = deserializer.deserialize_seq(SetVisitor {
|
||||
set_info,
|
||||
registry: self.registry,
|
||||
processor: self.processor,
|
||||
})?;
|
||||
dynamic_set.set_represented_type(Some(self.registration.type_info()));
|
||||
Ok(Box::new(dynamic_set))
|
||||
}
|
||||
TypeInfo::Tuple(tuple_info) => {
|
||||
let mut dynamic_tuple = deserializer.deserialize_tuple(
|
||||
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()));
|
||||
Ok(Box::new(dynamic_tuple))
|
||||
|
@ -370,13 +488,21 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
|
|||
== Some("core::option")
|
||||
&& enum_info.type_path_table().ident() == Some("Option")
|
||||
{
|
||||
deserializer
|
||||
.deserialize_option(OptionVisitor::new(enum_info, self.registry))?
|
||||
deserializer.deserialize_option(OptionVisitor {
|
||||
enum_info,
|
||||
registry: self.registry,
|
||||
processor: self.processor,
|
||||
})?
|
||||
} else {
|
||||
deserializer.deserialize_enum(
|
||||
enum_info.type_path_table().ident().unwrap(),
|
||||
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()));
|
||||
|
|
|
@ -15,30 +15,19 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`Enum`] values.
|
||||
///
|
||||
/// [`Enum`]: crate::Enum
|
||||
pub(super) struct EnumVisitor<'a> {
|
||||
enum_info: &'static EnumInfo,
|
||||
registration: &'a TypeRegistration,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct EnumVisitor<'a, P> {
|
||||
pub enum_info: &'static EnumInfo,
|
||||
pub registration: &'a TypeRegistration,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> EnumVisitor<'a> {
|
||||
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> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for EnumVisitor<'_, P> {
|
||||
type Value = DynamicEnum;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
|
@ -63,6 +52,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
|
|||
struct_info,
|
||||
registration: self.registration,
|
||||
registry: self.registry,
|
||||
processor: self.processor,
|
||||
},
|
||||
)?
|
||||
.into(),
|
||||
|
@ -71,9 +61,12 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
|
|||
*TupleLikeInfo::field_at(tuple_info, 0)?.ty(),
|
||||
self.registry,
|
||||
)?;
|
||||
let value = variant.newtype_variant_seed(
|
||||
TypedReflectDeserializer::new_internal(registration, self.registry),
|
||||
)?;
|
||||
let value =
|
||||
variant.newtype_variant_seed(TypedReflectDeserializer::new_internal(
|
||||
registration,
|
||||
self.registry,
|
||||
self.processor,
|
||||
))?;
|
||||
let mut dynamic_tuple = DynamicTuple::default();
|
||||
dynamic_tuple.insert_boxed(value);
|
||||
dynamic_tuple.into()
|
||||
|
@ -85,6 +78,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> {
|
|||
tuple_info,
|
||||
registration: self.registration,
|
||||
registry: self.registry,
|
||||
processor: self.processor,
|
||||
},
|
||||
)?
|
||||
.into(),
|
||||
|
@ -151,13 +145,14 @@ impl<'de> DeserializeSeed<'de> for VariantDeserializer {
|
|||
}
|
||||
}
|
||||
|
||||
struct StructVariantVisitor<'a> {
|
||||
struct StructVariantVisitor<'a, P> {
|
||||
struct_info: &'static StructVariantInfo,
|
||||
registration: &'a TypeRegistration,
|
||||
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;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
|
@ -168,24 +163,37 @@ impl<'a, 'de> Visitor<'de> for StructVariantVisitor<'a> {
|
|||
where
|
||||
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>
|
||||
where
|
||||
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,
|
||||
registration: &'a TypeRegistration,
|
||||
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;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
|
@ -196,6 +204,12 @@ impl<'a, 'de> Visitor<'de> for TupleVariantVisitor<'a> {
|
|||
where
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,31 +5,25 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{SeqAccess, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`List`] values.
|
||||
///
|
||||
/// [`List`]: crate::List
|
||||
pub(super) struct ListVisitor<'a> {
|
||||
list_info: &'static ListInfo,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct ListVisitor<'a, P> {
|
||||
pub list_info: &'static ListInfo,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> ListVisitor<'a> {
|
||||
pub fn new(list_info: &'static ListInfo, registry: &'a TypeRegistry) -> Self {
|
||||
Self {
|
||||
list_info,
|
||||
registry,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de> Visitor<'de> for ListVisitor<'a> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for ListVisitor<'_, P> {
|
||||
type Value = DynamicList;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
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
|
||||
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(
|
||||
registration,
|
||||
self.registry,
|
||||
self.processor.as_deref_mut(),
|
||||
))? {
|
||||
list.push_box(value);
|
||||
}
|
||||
|
|
|
@ -5,28 +5,25 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{MapAccess, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`Map`] values.
|
||||
///
|
||||
/// [`Map`]: crate::Map
|
||||
pub(super) struct MapVisitor<'a> {
|
||||
map_info: &'static MapInfo,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct MapVisitor<'a, P> {
|
||||
pub map_info: &'static MapInfo,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> MapVisitor<'a> {
|
||||
pub fn new(map_info: &'static MapInfo, registry: &'a TypeRegistry) -> Self {
|
||||
Self { map_info, registry }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de> Visitor<'de> for MapVisitor<'a> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for MapVisitor<'_, P> {
|
||||
type Value = DynamicMap;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
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
|
||||
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(
|
||||
key_registration,
|
||||
self.registry,
|
||||
self.processor.as_deref_mut(),
|
||||
))? {
|
||||
let value = map.next_value_seed(TypedReflectDeserializer::new_internal(
|
||||
value_registration,
|
||||
self.registry,
|
||||
self.processor.as_deref_mut(),
|
||||
))?;
|
||||
dynamic_map.insert_boxed(key, value);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
pub use deserialize_with_registry::*;
|
||||
pub use deserializer::*;
|
||||
pub use processor::*;
|
||||
pub use registrations::*;
|
||||
|
||||
mod arrays;
|
||||
|
@ -11,6 +12,7 @@ mod helpers;
|
|||
mod lists;
|
||||
mod maps;
|
||||
mod options;
|
||||
mod processor;
|
||||
mod registration_utils;
|
||||
mod registrations;
|
||||
mod sets;
|
||||
|
@ -24,12 +26,15 @@ mod tuples;
|
|||
mod tests {
|
||||
use bincode::Options;
|
||||
use core::{any::TypeId, f32::consts::PI, ops::RangeInclusive};
|
||||
use serde::de::IgnoredAny;
|
||||
use serde::Deserializer;
|
||||
|
||||
use serde::{de::DeserializeSeed, Deserialize};
|
||||
|
||||
use bevy_utils::{HashMap, HashSet};
|
||||
|
||||
use crate as bevy_reflect;
|
||||
use crate::serde::ReflectDeserializerProcessor;
|
||||
use crate::{self as bevy_reflect, TypeRegistration};
|
||||
use crate::{
|
||||
serde::{ReflectDeserializer, ReflectSerializer, TypedReflectDeserializer},
|
||||
DynamicEnum, FromReflect, PartialReflect, Reflect, ReflectDeserialize, TypeRegistry,
|
||||
|
@ -275,15 +280,14 @@ mod tests {
|
|||
let mut registry = get_registry();
|
||||
registry.register::<Foo>();
|
||||
let registration = registry.get(TypeId::of::<Foo>()).unwrap();
|
||||
let reflect_deserializer = TypedReflectDeserializer::new_internal(registration, ®istry);
|
||||
let reflect_deserializer = TypedReflectDeserializer::new(registration, ®istry);
|
||||
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_ref().as_partial_reflect())
|
||||
.unwrap();
|
||||
<Foo as FromReflect>::from_reflect(dynamic_output.as_partial_reflect()).unwrap();
|
||||
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()));
|
||||
}
|
||||
|
||||
#[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, ®istry, &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, ®istry, &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(®istry, &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(®istry, &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, ®istry, &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")]
|
||||
mod functions {
|
||||
use super::*;
|
||||
|
|
|
@ -8,22 +8,16 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{DeserializeSeed, Error, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`Option`] values.
|
||||
pub(super) struct OptionVisitor<'a> {
|
||||
enum_info: &'static EnumInfo,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct OptionVisitor<'a, P> {
|
||||
pub enum_info: &'static EnumInfo,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> OptionVisitor<'a> {
|
||||
pub fn new(enum_info: &'static EnumInfo, registry: &'a TypeRegistry) -> Self {
|
||||
Self {
|
||||
enum_info,
|
||||
registry,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for OptionVisitor<'_, P> {
|
||||
type Value = DynamicEnum;
|
||||
|
||||
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 => {
|
||||
let field = tuple_info.field_at(0).unwrap();
|
||||
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();
|
||||
value.insert_boxed(de.deserialize(deserializer)?);
|
||||
let mut option = DynamicEnum::default();
|
||||
|
|
213
crates/bevy_reflect/src/serde/de/processor.rs
Normal file
213
crates/bevy_reflect/src/serde/de/processor.rs
Normal 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))
|
||||
}
|
||||
}
|
|
@ -5,28 +5,25 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{SeqAccess, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`Set`] values.
|
||||
///
|
||||
/// [`Set`]: crate::Set
|
||||
pub(super) struct SetVisitor<'a> {
|
||||
set_info: &'static SetInfo,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct SetVisitor<'a, P> {
|
||||
pub set_info: &'static SetInfo,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> SetVisitor<'a> {
|
||||
pub fn new(set_info: &'static SetInfo, registry: &'a TypeRegistry) -> Self {
|
||||
Self { set_info, registry }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de> Visitor<'de> for SetVisitor<'a> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for SetVisitor<'_, P> {
|
||||
type Value = DynamicSet;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
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
|
||||
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(
|
||||
value_registration,
|
||||
self.registry,
|
||||
self.processor.as_deref_mut(),
|
||||
))? {
|
||||
dynamic_set.insert_boxed(value);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ use crate::{
|
|||
use core::slice::Iter;
|
||||
use serde::de::{Error, MapAccess, SeqAccess};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A helper trait for accessing type information from struct-like types.
|
||||
pub(super) trait StructLikeInfo {
|
||||
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`].
|
||||
///
|
||||
/// [struct-like]: StructLikeInfo
|
||||
pub(super) fn visit_struct<'de, T, V>(
|
||||
pub(super) fn visit_struct<'de, T, V, P>(
|
||||
map: &mut V,
|
||||
info: &'static T,
|
||||
registration: &TypeRegistration,
|
||||
registry: &TypeRegistry,
|
||||
mut processor: Option<&mut P>,
|
||||
) -> Result<DynamicStruct, V::Error>
|
||||
where
|
||||
T: StructLikeInfo,
|
||||
V: MapAccess<'de>,
|
||||
P: ReflectDeserializerProcessor,
|
||||
{
|
||||
let mut dynamic_struct = DynamicStruct::default();
|
||||
while let Some(Ident(key)) = map.next_key::<Ident>()? {
|
||||
|
@ -107,6 +111,7 @@ where
|
|||
let value = map.next_value_seed(TypedReflectDeserializer::new_internal(
|
||||
registration,
|
||||
registry,
|
||||
processor.as_deref_mut(),
|
||||
))?;
|
||||
dynamic_struct.insert_boxed(&key, value);
|
||||
}
|
||||
|
@ -129,15 +134,17 @@ where
|
|||
/// Deserializes a [struct-like] type from a sequence of fields, returning a [`DynamicStruct`].
|
||||
///
|
||||
/// [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,
|
||||
info: &T,
|
||||
registration: &TypeRegistration,
|
||||
registry: &TypeRegistry,
|
||||
mut processor: Option<&mut P>,
|
||||
) -> Result<DynamicStruct, V::Error>
|
||||
where
|
||||
T: StructLikeInfo,
|
||||
V: SeqAccess<'de>,
|
||||
P: ReflectDeserializerProcessor,
|
||||
{
|
||||
let mut dynamic_struct = DynamicStruct::default();
|
||||
|
||||
|
@ -167,6 +174,7 @@ where
|
|||
.next_element_seed(TypedReflectDeserializer::new_internal(
|
||||
try_get_registration(*info.field_at(index)?.ty(), registry)?,
|
||||
registry,
|
||||
processor.as_deref_mut(),
|
||||
))?
|
||||
.ok_or_else(|| Error::invalid_length(index, &len.to_string().as_str()))?;
|
||||
dynamic_struct.insert_boxed(name, value);
|
||||
|
|
|
@ -5,30 +5,19 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{MapAccess, SeqAccess, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`Struct`] values.
|
||||
///
|
||||
/// [`Struct`]: crate::Struct
|
||||
pub(super) struct StructVisitor<'a> {
|
||||
struct_info: &'static StructInfo,
|
||||
registration: &'a TypeRegistration,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct StructVisitor<'a, P> {
|
||||
pub struct_info: &'static StructInfo,
|
||||
pub registration: &'a TypeRegistration,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> StructVisitor<'a> {
|
||||
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> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for StructVisitor<'_, P> {
|
||||
type Value = DynamicStruct;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
|
@ -39,13 +28,25 @@ impl<'a, 'de> Visitor<'de> for StructVisitor<'a> {
|
|||
where
|
||||
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>
|
||||
where
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,30 +7,19 @@ use serde::de::{DeserializeSeed, SeqAccess, Visitor};
|
|||
|
||||
use super::{registration_utils::try_get_registration, TypedReflectDeserializer};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`TupleStruct`] values.
|
||||
///
|
||||
/// [`TupleStruct`]: crate::TupleStruct
|
||||
pub(super) struct TupleStructVisitor<'a> {
|
||||
tuple_struct_info: &'static TupleStructInfo,
|
||||
registration: &'a TypeRegistration,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct TupleStructVisitor<'a, P> {
|
||||
pub tuple_struct_info: &'static TupleStructInfo,
|
||||
pub registration: &'a TypeRegistration,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> TupleStructVisitor<'a> {
|
||||
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> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for TupleStructVisitor<'_, P> {
|
||||
type Value = DynamicTupleStruct;
|
||||
|
||||
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.registration,
|
||||
self.registry,
|
||||
self.processor,
|
||||
)
|
||||
.map(DynamicTupleStruct::from)
|
||||
}
|
||||
|
@ -71,7 +61,7 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> {
|
|||
self.registry,
|
||||
)?;
|
||||
let reflect_deserializer =
|
||||
TypedReflectDeserializer::new_internal(registration, self.registry);
|
||||
TypedReflectDeserializer::new_internal(registration, self.registry, self.processor);
|
||||
let value = reflect_deserializer.deserialize(deserializer)?;
|
||||
|
||||
tuple.insert_boxed(value.into_partial_reflect());
|
||||
|
|
|
@ -8,6 +8,8 @@ use crate::{
|
|||
};
|
||||
use serde::de::{Error, SeqAccess};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
pub(super) trait TupleLikeInfo {
|
||||
fn field_at<E: Error>(&self, index: usize) -> Result<&UnnamedField, E>;
|
||||
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`].
|
||||
///
|
||||
/// [tuple-like]: TupleLikeInfo
|
||||
pub(super) fn visit_tuple<'de, T, V>(
|
||||
pub(super) fn visit_tuple<'de, T, V, P>(
|
||||
seq: &mut V,
|
||||
info: &T,
|
||||
registration: &TypeRegistration,
|
||||
registry: &TypeRegistry,
|
||||
mut processor: Option<&mut P>,
|
||||
) -> Result<DynamicTuple, V::Error>
|
||||
where
|
||||
T: TupleLikeInfo,
|
||||
V: SeqAccess<'de>,
|
||||
P: ReflectDeserializerProcessor,
|
||||
{
|
||||
let mut tuple = DynamicTuple::default();
|
||||
|
||||
|
@ -95,6 +99,7 @@ where
|
|||
.next_element_seed(TypedReflectDeserializer::new_internal(
|
||||
try_get_registration(*info.field_at(index)?.ty(), registry)?,
|
||||
registry,
|
||||
processor.as_deref_mut(),
|
||||
))?
|
||||
.ok_or_else(|| Error::invalid_length(index, &len.to_string().as_str()))?;
|
||||
tuple.insert_boxed(value);
|
||||
|
|
|
@ -4,30 +4,19 @@ use crate::{
|
|||
use core::{fmt, fmt::Formatter};
|
||||
use serde::de::{SeqAccess, Visitor};
|
||||
|
||||
use super::ReflectDeserializerProcessor;
|
||||
|
||||
/// A [`Visitor`] for deserializing [`Tuple`] values.
|
||||
///
|
||||
/// [`Tuple`]: crate::Tuple
|
||||
pub(super) struct TupleVisitor<'a> {
|
||||
tuple_info: &'static TupleInfo,
|
||||
registration: &'a TypeRegistration,
|
||||
registry: &'a TypeRegistry,
|
||||
pub(super) struct TupleVisitor<'a, P> {
|
||||
pub tuple_info: &'static TupleInfo,
|
||||
pub registration: &'a TypeRegistration,
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub processor: Option<&'a mut P>,
|
||||
}
|
||||
|
||||
impl<'a> TupleVisitor<'a> {
|
||||
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> {
|
||||
impl<'de, P: ReflectDeserializerProcessor> Visitor<'de> for TupleVisitor<'_, P> {
|
||||
type Value = DynamicTuple;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
|
@ -38,6 +27,12 @@ impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> {
|
|||
where
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue