diff --git a/crates/bevy_reflect/src/serde/de/arrays.rs b/crates/bevy_reflect/src/serde/de/arrays.rs index 24d009716a..1e9dafae3c 100644 --- a/crates/bevy_reflect/src/serde/de/arrays.rs +++ b/crates/bevy_reflect/src/serde/de/arrays.rs @@ -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(self, mut seq: V) -> Result + fn visit_seq(mut self, mut seq: V) -> Result 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); } diff --git a/crates/bevy_reflect/src/serde/de/deserializer.rs b/crates/bevy_reflect/src/serde/de/deserializer.rs index a1a97e3877..a177772ce2 100644 --- a/crates/bevy_reflect/src/serde/de/deserializer.rs +++ b/crates/bevy_reflect/src/serde/de/deserializer.rs @@ -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`]: 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; fn deserialize(self, deserializer: D) -> Result 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; 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::()?.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`]: 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; - fn deserialize(self, deserializer: D) -> Result + fn deserialize(mut self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { let deserialize_internal = || -> Result { + // 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())); diff --git a/crates/bevy_reflect/src/serde/de/enums.rs b/crates/bevy_reflect/src/serde/de/enums.rs index ecdcc1435c..21cbf46f9e 100644 --- a/crates/bevy_reflect/src/serde/de/enums.rs +++ b/crates/bevy_reflect/src/serde/de/enums.rs @@ -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(self, mut map: V) -> Result 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, + ) } } diff --git a/crates/bevy_reflect/src/serde/de/lists.rs b/crates/bevy_reflect/src/serde/de/lists.rs index 7d4ab44f8a..b85e46874a 100644 --- a/crates/bevy_reflect/src/serde/de/lists.rs +++ b/crates/bevy_reflect/src/serde/de/lists.rs @@ -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(self, mut seq: V) -> Result + fn visit_seq(mut self, mut seq: V) -> Result 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); } diff --git a/crates/bevy_reflect/src/serde/de/maps.rs b/crates/bevy_reflect/src/serde/de/maps.rs index fbb5f9d449..95b1c1f83e 100644 --- a/crates/bevy_reflect/src/serde/de/maps.rs +++ b/crates/bevy_reflect/src/serde/de/maps.rs @@ -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(self, mut map: V) -> Result + fn visit_map(mut self, mut map: V) -> Result 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); } diff --git a/crates/bevy_reflect/src/serde/de/mod.rs b/crates/bevy_reflect/src/serde/de/mod.rs index 92a43ed175..b1ada1835e 100644 --- a/crates/bevy_reflect/src/serde/de/mod.rs +++ b/crates/bevy_reflect/src/serde/de/mod.rs @@ -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::(); let registration = registry.get(TypeId::of::()).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 = - ::from_reflect(dynamic_output.as_ref().as_partial_reflect()) - .unwrap(); + ::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` 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, D>, D::Error> + where + D: Deserializer<'de>, + { + if registration.type_id() == TypeId::of::() { + 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::(); + let registration = registry.get(TypeId::of::()).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 = + ::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, D>, D::Error> + where + D: Deserializer<'de>, + { + if registration.type_id() == TypeId::of::() { + let _ = deserializer.deserialize_ignored_any(IgnoredAny); + Ok(Ok(Box::new(123_i32))) + } else if registration.type_id() == TypeId::of::() { + 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::(); + let registration = registry.get(TypeId::of::()).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 = + ::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, D>, D::Error> + where + D: Deserializer<'de>, + { + if registration.type_id() == TypeId::of::() { + 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, 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, D>, D::Error> + where + D: Deserializer<'de>, + { + if registration.type_id() == TypeId::of::() { + 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::(); + let registration = registry.get(TypeId::of::()).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!(::from_reflect(dynamic_output.as_partial_reflect()).is_none()); + } + #[cfg(feature = "functions")] mod functions { use super::*; diff --git a/crates/bevy_reflect/src/serde/de/options.rs b/crates/bevy_reflect/src/serde/de/options.rs index de9ded5075..f347c4a67d 100644 --- a/crates/bevy_reflect/src/serde/de/options.rs +++ b/crates/bevy_reflect/src/serde/de/options.rs @@ -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(); diff --git a/crates/bevy_reflect/src/serde/de/processor.rs b/crates/bevy_reflect/src/serde/de/processor.rs new file mode 100644 index 0000000000..7dbe0388b4 --- /dev/null +++ b/crates/bevy_reflect/src/serde/de/processor.rs @@ -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`], 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); +/// # #[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 { unimplemented!() } +/// # } +/// # +/// # struct ReflectHandle; +/// # impl TypeData for ReflectHandle { +/// # fn clone_type_data(&self) -> Box { +/// # 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; +/// #[derive(Debug, Clone, Reflect)] +/// struct MyAsset { +/// name: String, +/// mesh: Handle, +/// } +/// +/// fn load( +/// asset_bytes: &[u8], +/// type_registry: &TypeRegistry, +/// load_context: &mut LoadContext, +/// ) -> Result { +/// 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, D>, D::Error> +/// where +/// D: Deserializer<'de>, +/// { +/// let Some(reflect_handle) = registration.data::() 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 = 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`] 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, D>, D::Error> + /// where + /// D: serde::Deserializer<'de> + /// { + /// if registration.type_id() == TypeId::of::() { + /// _ = 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, 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, D>, D::Error> + where + D: serde::Deserializer<'de>, + { + Ok(Err(deserializer)) + } +} diff --git a/crates/bevy_reflect/src/serde/de/sets.rs b/crates/bevy_reflect/src/serde/de/sets.rs index faecf5bc39..ed1a469df3 100644 --- a/crates/bevy_reflect/src/serde/de/sets.rs +++ b/crates/bevy_reflect/src/serde/de/sets.rs @@ -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(self, mut set: V) -> Result + fn visit_seq(mut self, mut set: V) -> Result 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); } diff --git a/crates/bevy_reflect/src/serde/de/struct_utils.rs b/crates/bevy_reflect/src/serde/de/struct_utils.rs index 0833678753..8f3a3250ff 100644 --- a/crates/bevy_reflect/src/serde/de/struct_utils.rs +++ b/crates/bevy_reflect/src/serde/de/struct_utils.rs @@ -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(&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 where T: StructLikeInfo, V: MapAccess<'de>, + P: ReflectDeserializerProcessor, { let mut dynamic_struct = DynamicStruct::default(); while let Some(Ident(key)) = map.next_key::()? { @@ -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 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); diff --git a/crates/bevy_reflect/src/serde/de/structs.rs b/crates/bevy_reflect/src/serde/de/structs.rs index 750c739e8e..0135e96358 100644 --- a/crates/bevy_reflect/src/serde/de/structs.rs +++ b/crates/bevy_reflect/src/serde/de/structs.rs @@ -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(self, mut map: V) -> Result 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, + ) } } diff --git a/crates/bevy_reflect/src/serde/de/tuple_structs.rs b/crates/bevy_reflect/src/serde/de/tuple_structs.rs index c9703cb504..af33b8d0b3 100644 --- a/crates/bevy_reflect/src/serde/de/tuple_structs.rs +++ b/crates/bevy_reflect/src/serde/de/tuple_structs.rs @@ -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()); diff --git a/crates/bevy_reflect/src/serde/de/tuple_utils.rs b/crates/bevy_reflect/src/serde/de/tuple_utils.rs index ae49fe4084..9c96d78a67 100644 --- a/crates/bevy_reflect/src/serde/de/tuple_utils.rs +++ b/crates/bevy_reflect/src/serde/de/tuple_utils.rs @@ -8,6 +8,8 @@ use crate::{ }; use serde::de::{Error, SeqAccess}; +use super::ReflectDeserializerProcessor; + pub(super) trait TupleLikeInfo { fn field_at(&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 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); diff --git a/crates/bevy_reflect/src/serde/de/tuples.rs b/crates/bevy_reflect/src/serde/de/tuples.rs index ea06ad3154..87b9fc81c9 100644 --- a/crates/bevy_reflect/src/serde/de/tuples.rs +++ b/crates/bevy_reflect/src/serde/de/tuples.rs @@ -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, + ) } }