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}