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}