bevy_reflect/serde/de/deserialize_with_registry.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use crate::serde::de::error_utils::make_custom_error;
use crate::{FromType, PartialReflect, TypeRegistry};
use serde::Deserializer;
/// Trait used to provide finer control when deserializing a reflected type with one of
/// the reflection deserializers.
///
/// This trait is the reflection equivalent of `serde`'s [`Deserialize`] trait.
/// The main difference is that this trait provides access to the [`TypeRegistry`],
/// which means that we can use the registry and all its stored type information
/// to deserialize our type.
///
/// This can be useful when writing a custom reflection deserializer where we may
/// want to handle parts of the deserialization process, but temporarily pass control
/// to the standard reflection deserializer for other parts.
///
/// For the serialization equivalent of this trait, see [`SerializeWithRegistry`].
///
/// # Rationale
///
/// Without this trait and its associated [type data], such a deserializer would have to
/// write out all of the deserialization logic itself, possibly including
/// unnecessary code duplication and trivial implementations.
///
/// This is because a normal [`Deserialize`] implementation has no knowledge of the
/// [`TypeRegistry`] and therefore cannot create a reflection-based deserializer for
/// nested items.
///
/// # Implementors
///
/// In order for this to work with the reflection deserializers like [`TypedReflectDeserializer`]
/// and [`ReflectDeserializer`], implementors should be sure to register the
/// [`ReflectDeserializeWithRegistry`] type data.
/// This can be done [via the registry] or by adding `#[reflect(DeserializeWithRegistry)]` to
/// the type definition.
///
/// [`Deserialize`]: ::serde::Deserialize
/// [`SerializeWithRegistry`]: crate::serde::SerializeWithRegistry
/// [type data]: ReflectDeserializeWithRegistry
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer
/// [via the registry]: TypeRegistry::register_type_data
pub trait DeserializeWithRegistry<'de>: PartialReflect + Sized {
fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error>
where
D: Deserializer<'de>;
}
/// Type data used to deserialize a [`PartialReflect`] type with a custom [`DeserializeWithRegistry`] implementation.
#[derive(Clone)]
pub struct ReflectDeserializeWithRegistry {
deserialize: fn(
deserializer: &mut dyn erased_serde::Deserializer,
registry: &TypeRegistry,
) -> Result<Box<dyn PartialReflect>, erased_serde::Error>,
}
impl ReflectDeserializeWithRegistry {
/// Deserialize a [`PartialReflect`] type with this type data's custom [`DeserializeWithRegistry`] implementation.
pub fn deserialize<'de, D>(
&self,
deserializer: D,
registry: &TypeRegistry,
) -> Result<Box<dyn PartialReflect>, D::Error>
where
D: Deserializer<'de>,
{
let mut erased = <dyn erased_serde::Deserializer>::erase(deserializer);
(self.deserialize)(&mut erased, registry).map_err(make_custom_error)
}
}
impl<T: PartialReflect + for<'de> DeserializeWithRegistry<'de>> FromType<T>
for ReflectDeserializeWithRegistry
{
fn from_type() -> Self {
Self {
deserialize: |deserializer, registry| {
Ok(Box::new(T::deserialize(deserializer, registry)?))
},
}
}
}