Path: blob/main/crates/bevy_reflect/src/serde/de/processor.rs
6600 views
use crate::{PartialReflect, TypeRegistration, TypeRegistry};1use alloc::boxed::Box;23/// Allows overriding the default deserialization behavior of4/// [`ReflectDeserializer`] and [`TypedReflectDeserializer`] for specific5/// [`TypeRegistration`]s.6///7/// When deserializing a reflected value, you may want to override the default8/// behavior and use your own logic for deserialization. This logic may also9/// be context-dependent, and only apply for a single use of your10/// [`ReflectDeserializer`]. To achieve this, you can create a processor and11/// pass it in to your deserializer.12///13/// Whenever the deserializer attempts to deserialize a value, it will first14/// call [`try_deserialize`] on your processor, which may take ownership of the15/// deserializer and give back a [`Box<dyn PartialReflect>`], or return16/// ownership of the deserializer back, and continue with the default logic.17///18/// The serialization equivalent of this is [`ReflectSerializerProcessor`].19///20/// # Compared to [`DeserializeWithRegistry`]21///22/// [`DeserializeWithRegistry`] allows you to define how your type will be23/// deserialized by a [`TypedReflectDeserializer`], given the extra context of24/// the [`TypeRegistry`]. If your type can be deserialized entirely from that,25/// then you should prefer implementing that trait instead of using a processor.26///27/// However, you may need more context-dependent data which is only present in28/// the scope where you create the [`TypedReflectDeserializer`]. For example, in29/// an asset loader, the `&mut LoadContext` you get is only valid from within30/// the `load` function. This is where a processor is useful, as the processor31/// can capture local variables.32///33/// A [`ReflectDeserializerProcessor`] always takes priority over a34/// [`DeserializeWithRegistry`] implementation, so this is also useful for35/// overriding deserialization behavior if you need to do something custom.36///37/// # Examples38///39/// Deserializing a reflected value in an asset loader, and replacing asset40/// handles with a loaded equivalent:41///42/// ```43/// # use bevy_reflect::serde::{ReflectDeserializer, ReflectDeserializerProcessor};44/// # use bevy_reflect::{PartialReflect, Reflect, TypeData, TypeRegistration, TypeRegistry};45/// # use serde::de::{DeserializeSeed, Deserializer, Visitor};46/// # use std::marker::PhantomData;47/// #48/// # #[derive(Debug, Clone, Reflect)]49/// # struct LoadedUntypedAsset;50/// # #[derive(Debug, Clone, Reflect)]51/// # struct Handle<T: Reflect>(T);52/// # #[derive(Debug, Clone, Reflect)]53/// # struct Mesh;54/// #55/// # struct LoadContext;56/// # impl LoadContext {57/// # fn load(&mut self) -> &mut Self { unimplemented!() }58/// # fn with_asset_type_id(&mut self, (): ()) -> &mut Self { unimplemented!() }59/// # fn untyped(&mut self) -> &mut Self { unimplemented!() }60/// # fn load_asset(&mut self, (): ()) -> Handle<LoadedUntypedAsset> { unimplemented!() }61/// # }62/// #63/// # struct ReflectHandle;64/// # impl TypeData for ReflectHandle {65/// # fn clone_type_data(&self) -> Box<dyn TypeData> {66/// # unimplemented!()67/// # }68/// # }69/// # impl ReflectHandle {70/// # fn asset_type_id(&self) {71/// # unimplemented!()72/// # }73/// # }74/// #75/// # struct AssetPathVisitor;76/// # impl<'de> Visitor<'de> for AssetPathVisitor {77/// # type Value = ();78/// # fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { unimplemented!() }79/// # }80/// # type AssetError = Box<dyn core::error::Error>;81/// #[derive(Debug, Clone, Reflect)]82/// struct MyAsset {83/// name: String,84/// mesh: Handle<Mesh>,85/// }86///87/// fn load(88/// asset_bytes: &[u8],89/// type_registry: &TypeRegistry,90/// load_context: &mut LoadContext,91/// ) -> Result<MyAsset, AssetError> {92/// struct HandleProcessor<'a> {93/// load_context: &'a mut LoadContext,94/// }95///96/// impl ReflectDeserializerProcessor for HandleProcessor<'_> {97/// fn try_deserialize<'de, D>(98/// &mut self,99/// registration: &TypeRegistration,100/// _registry: &TypeRegistry,101/// deserializer: D,102/// ) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>103/// where104/// D: Deserializer<'de>,105/// {106/// let Some(reflect_handle) = registration.data::<ReflectHandle>() else {107/// // we don't want to deserialize this - give the deserializer back108/// return Ok(Err(deserializer));109/// };110///111/// let asset_type_id = reflect_handle.asset_type_id();112/// let asset_path = deserializer.deserialize_str(AssetPathVisitor)?;113///114/// let handle: Handle<LoadedUntypedAsset> = self.load_context115/// .load()116/// .with_asset_type_id(asset_type_id)117/// .untyped()118/// .load_asset(asset_path);119/// # let _: Result<_, ()> = {120/// Ok(Box::new(handle))121/// # };122/// # unimplemented!()123/// }124/// }125///126/// let mut ron_deserializer = ron::Deserializer::from_bytes(asset_bytes)?;127/// let mut processor = HandleProcessor { load_context };128/// let reflect_deserializer =129/// ReflectDeserializer::with_processor(type_registry, &mut processor);130/// let asset = reflect_deserializer.deserialize(&mut ron_deserializer)?;131/// # unimplemented!()132/// }133/// ```134///135/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer136/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer137/// [`try_deserialize`]: Self::try_deserialize138/// [`DeserializeWithRegistry`]: crate::serde::DeserializeWithRegistry139/// [`ReflectSerializerProcessor`]: crate::serde::ReflectSerializerProcessor140pub trait ReflectDeserializerProcessor {141/// Attempts to deserialize the value which a [`TypedReflectDeserializer`]142/// is currently looking at, and knows the type of.143///144/// If you've read the `registration` and want to override the default145/// deserialization, return `Ok(Ok(value))` with the boxed reflected value146/// that you want to assign this value to. The type inside the box must147/// be the same one as the `registration` is for, otherwise future148/// reflection operations (such as using [`FromReflect`] to convert the149/// resulting [`Box<dyn PartialReflect>`] into a concrete type) will fail.150///151/// If you don't want to override the deserialization, return ownership of152/// the deserializer back via `Ok(Err(deserializer))`.153///154/// Note that, if you do want to return a value, you *must* read from the155/// deserializer passed to this function (you are free to ignore the result156/// though). Otherwise, the deserializer will be in an inconsistent state,157/// and future value parsing will fail.158///159/// # Examples160///161/// Correct way to return a constant value (not using any output from the162/// deserializer):163///164/// ```165/// # use bevy_reflect::{TypeRegistration, PartialReflect, TypeRegistry};166/// # use bevy_reflect::serde::ReflectDeserializerProcessor;167/// # use core::any::TypeId;168/// use serde::de::IgnoredAny;169///170/// struct ConstantI32Processor;171///172/// impl ReflectDeserializerProcessor for ConstantI32Processor {173/// fn try_deserialize<'de, D>(174/// &mut self,175/// registration: &TypeRegistration,176/// _registry: &TypeRegistry,177/// deserializer: D,178/// ) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>179/// where180/// D: serde::Deserializer<'de>181/// {182/// if registration.type_id() == TypeId::of::<i32>() {183/// _ = deserializer.deserialize_ignored_any(IgnoredAny);184/// Ok(Ok(Box::new(42_i32)))185/// } else {186/// Ok(Err(deserializer))187/// }188/// }189/// }190/// ```191///192/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer193/// [`FromReflect`]: crate::FromReflect194fn try_deserialize<'de, D>(195&mut self,196registration: &TypeRegistration,197registry: &TypeRegistry,198deserializer: D,199) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>200where201D: serde::Deserializer<'de>;202}203204impl ReflectDeserializerProcessor for () {205fn try_deserialize<'de, D>(206&mut self,207_registration: &TypeRegistration,208_registry: &TypeRegistry,209deserializer: D,210) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>211where212D: serde::Deserializer<'de>,213{214Ok(Err(deserializer))215}216}217218219