bevy_reflect/serde/de/
deserialize_with_registry.rs

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