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