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