bevy_reflect/serde/ser/
serialize_with_registry.rs

1use crate::{FromType, Reflect, TypeRegistry};
2use serde::{Serialize, Serializer};
3
4/// Trait used to provide finer control when serializing a reflected type with one of
5/// the reflection serializers.
6///
7/// This trait is the reflection equivalent of `serde`'s [`Serialize`] trait.
8/// The main difference is that this trait provides access to the [`TypeRegistry`],
9/// which means that we can use the registry and all its stored type information
10/// to serialize our type.
11///
12/// This can be useful when writing a custom reflection serializer where we may
13/// want to handle parts of the serialization process, but temporarily pass control
14/// to the standard reflection serializer for other parts.
15///
16/// For the deserialization equivalent of this trait, see [`DeserializeWithRegistry`].
17///
18/// # Rationale
19///
20/// Without this trait and its associated [type data], such a serializer would have to
21/// write out all of the serialization logic itself, possibly including
22/// unnecessary code duplication and trivial implementations.
23///
24/// This is because a normal [`Serialize`] implementation has no knowledge of the
25/// [`TypeRegistry`] and therefore cannot create a reflection-based serializer for
26/// nested items.
27///
28/// # Implementors
29///
30/// In order for this to work with the reflection serializers like [`TypedReflectSerializer`]
31/// and [`ReflectSerializer`], implementors should be sure to register the
32/// [`ReflectSerializeWithRegistry`] type data.
33/// This can be done [via the registry] or by adding `#[reflect(SerializeWithRegistry)]` to
34/// the type definition.
35///
36/// [`DeserializeWithRegistry`]: crate::serde::DeserializeWithRegistry
37/// [type data]: ReflectSerializeWithRegistry
38/// [`TypedReflectSerializer`]: crate::serde::TypedReflectSerializer
39/// [`ReflectSerializer`]: crate::serde::ReflectSerializer
40/// [via the registry]: TypeRegistry::register_type_data
41pub trait SerializeWithRegistry {
42    fn serialize<S>(&self, serializer: S, registry: &TypeRegistry) -> Result<S::Ok, S::Error>
43    where
44        S: Serializer;
45}
46
47/// Type data used to serialize a [`Reflect`] type with a custom [`SerializeWithRegistry`] implementation.
48#[derive(Clone)]
49pub struct ReflectSerializeWithRegistry {
50    serialize: for<'a> fn(
51        value: &'a dyn Reflect,
52        registry: &'a TypeRegistry,
53    ) -> Box<dyn erased_serde::Serialize + 'a>,
54}
55
56impl ReflectSerializeWithRegistry {
57    /// Serialize a [`Reflect`] type with this type data's custom [`SerializeWithRegistry`] implementation.
58    pub fn serialize<S>(
59        &self,
60        value: &dyn Reflect,
61        serializer: S,
62        registry: &TypeRegistry,
63    ) -> Result<S::Ok, S::Error>
64    where
65        S: Serializer,
66    {
67        ((self.serialize)(value, registry)).serialize(serializer)
68    }
69}
70
71impl<T: Reflect + SerializeWithRegistry> FromType<T> for ReflectSerializeWithRegistry {
72    fn from_type() -> Self {
73        Self {
74            serialize: |value: &dyn Reflect, registry| {
75                let value = value.downcast_ref::<T>().unwrap_or_else(|| {
76                    panic!(
77                        "Expected value to be of type {:?} but received {:?}",
78                        core::any::type_name::<T>(),
79                        value.reflect_type_path()
80                    )
81                });
82                Box::new(SerializableWithRegistry { value, registry })
83            },
84        }
85    }
86}
87
88struct SerializableWithRegistry<'a, T: SerializeWithRegistry> {
89    value: &'a T,
90    registry: &'a TypeRegistry,
91}
92
93impl<'a, T: SerializeWithRegistry> Serialize for SerializableWithRegistry<'a, T> {
94    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
95    where
96        S: Serializer,
97    {
98        self.value.serialize(serializer, self.registry)
99    }
100}