bevy_reflect/serde/ser/processor.rs
1use serde::Serializer;
2
3use crate::{PartialReflect, TypeRegistry};
4
5/// Allows overriding the default serialization behavior of
6/// [`ReflectSerializer`] and [`TypedReflectSerializer`] for specific values.
7///
8/// When serializing a reflected value, you may want to override the default
9/// behavior and use your own logic for serialization. This logic may also be
10/// context-dependent, and only apply for a single use of your
11/// [`ReflectSerializer`]. To achieve this, you can create a processor and pass
12/// it into your serializer.
13///
14/// Whenever the serializer attempts to serialize a value, it will first call
15/// [`try_serialize`] on your processor, which may take ownership of the
16/// serializer and write into the serializer (successfully or not), or return
17/// ownership of the serializer back, and continue with the default logic.
18///
19/// The deserialization equivalent of this is [`ReflectDeserializerProcessor`].
20///
21/// # Compared to [`SerializeWithRegistry`]
22///
23/// [`SerializeWithRegistry`] allows you to define how your type will be
24/// serialized by a [`TypedReflectSerializer`], given the extra context of the
25/// [`TypeRegistry`]. If your type can be serialized entirely using that, then
26/// you should prefer implementing that trait instead of using a processor.
27///
28/// However, you may need more context-dependent data which is only present in
29/// the scope where you create the [`TypedReflectSerializer`]. For example, if
30/// you need to use a reference to a value while serializing, then there is no
31/// way to do this with [`SerializeWithRegistry`] as you can't pass that
32/// reference into anywhere. This is where a processor is useful, as the
33/// processor can capture local variables.
34///
35/// A [`ReflectSerializerProcessor`] always takes priority over a
36/// [`SerializeWithRegistry`] implementation, so this is also useful for
37/// overriding serialization behavior if you need to do something custom.
38///
39/// # Examples
40///
41/// Serializing a reflected value when saving an asset to disk, and replacing
42/// asset handles with the handle path (if it has one):
43///
44/// ```
45/// # use core::any::Any;
46/// # use serde::Serialize;
47/// # use bevy_reflect::{PartialReflect, Reflect, TypeData, TypeRegistry};
48/// # use bevy_reflect::serde::{ReflectSerializer, ReflectSerializerProcessor};
49/// #
50/// # #[derive(Debug, Clone, Reflect)]
51/// # struct Handle<T>(T);
52/// # #[derive(Debug, Clone, Reflect)]
53/// # struct Mesh;
54/// #
55/// # struct ReflectHandle;
56/// # impl TypeData for ReflectHandle {
57/// # fn clone_type_data(&self) -> Box<dyn TypeData> {
58/// # unimplemented!()
59/// # }
60/// # }
61/// # impl ReflectHandle {
62/// # fn downcast_handle_untyped(&self, handle: &(dyn Any + 'static)) -> Option<UntypedHandle> {
63/// # unimplemented!()
64/// # }
65/// # }
66/// #
67/// # #[derive(Debug, Clone)]
68/// # struct UntypedHandle;
69/// # impl UntypedHandle {
70/// # fn path(&self) -> Option<&str> {
71/// # unimplemented!()
72/// # }
73/// # }
74/// # type AssetError = Box<dyn core::error::Error>;
75/// #
76/// #[derive(Debug, Clone, Reflect)]
77/// struct MyAsset {
78/// name: String,
79/// mesh: Handle<Mesh>,
80/// }
81///
82/// struct HandleProcessor;
83///
84/// impl ReflectSerializerProcessor for HandleProcessor {
85/// fn try_serialize<S>(
86/// &self,
87/// value: &dyn PartialReflect,
88/// registry: &TypeRegistry,
89/// serializer: S,
90/// ) -> Result<Result<S::Ok, S>, S::Error>
91/// where
92/// S: serde::Serializer,
93/// {
94/// let Some(value) = value.try_as_reflect() else {
95/// // we don't have any info on this type; do the default serialization logic
96/// return Ok(Err(serializer));
97/// };
98/// let type_id = value.reflect_type_info().type_id();
99/// let Some(reflect_handle) = registry.get_type_data::<ReflectHandle>(type_id) else {
100/// // this isn't a `Handle<T>`
101/// return Ok(Err(serializer));
102/// };
103///
104/// let untyped_handle = reflect_handle
105/// .downcast_handle_untyped(value.as_any())
106/// .unwrap();
107/// if let Some(path) = untyped_handle.path() {
108/// Ok(Ok(serializer.serialize_str(path)?))
109/// } else {
110/// Ok(Ok(serializer.serialize_unit()?))
111/// }
112/// }
113/// }
114///
115/// fn save(type_registry: &TypeRegistry, asset: &MyAsset) -> Result<Vec<u8>, AssetError> {
116/// let mut asset_bytes = Vec::new();
117///
118/// let processor = HandleProcessor;
119/// let serializer = ReflectSerializer::with_processor(asset, type_registry, &processor);
120/// let mut ron_serializer = ron::Serializer::new(&mut asset_bytes, None)?;
121///
122/// serializer.serialize(&mut ron_serializer)?;
123/// Ok(asset_bytes)
124/// }
125/// ```
126///
127/// [`ReflectSerializer`]: crate::serde::ReflectSerializer
128/// [`TypedReflectSerializer`]: crate::serde::TypedReflectSerializer
129/// [`try_serialize`]: Self::try_serialize
130/// [`SerializeWithRegistry`]: crate::serde::SerializeWithRegistry
131/// [`ReflectDeserializerProcessor`]: crate::serde::ReflectDeserializerProcessor
132pub trait ReflectSerializerProcessor {
133 /// Attempts to serialize the value which a [`TypedReflectSerializer`] is
134 /// currently looking at.
135 ///
136 /// If you want to override the default serialization, return
137 /// `Ok(Ok(value))` with an `Ok` output from the serializer.
138 ///
139 /// If you don't want to override the serialization, return ownership of
140 /// the serializer back via `Ok(Err(serializer))`.
141 ///
142 /// You can use the type registry to read info about the type you're
143 /// serializing, or just try to downcast the value directly:
144 ///
145 /// ```
146 /// # use bevy_reflect::{TypeRegistration, TypeRegistry, PartialReflect};
147 /// # use bevy_reflect::serde::ReflectSerializerProcessor;
148 /// # use core::any::TypeId;
149 /// struct I32AsStringProcessor;
150 ///
151 /// impl ReflectSerializerProcessor for I32AsStringProcessor {
152 /// fn try_serialize<S>(
153 /// &self,
154 /// value: &dyn PartialReflect,
155 /// registry: &TypeRegistry,
156 /// serializer: S,
157 /// ) -> Result<Result<S::Ok, S>, S::Error>
158 /// where
159 /// S: serde::Serializer
160 /// {
161 /// if let Some(value) = value.try_downcast_ref::<i32>() {
162 /// let value_as_string = format!("{value:?}");
163 /// Ok(Ok(serializer.serialize_str(&value_as_string)?))
164 /// } else {
165 /// // Not an `i32`, just do the default serialization
166 /// Ok(Err(serializer))
167 /// }
168 /// }
169 /// }
170 /// ```
171 ///
172 /// [`TypedReflectSerializer`]: crate::serde::TypedReflectSerializer
173 /// [`Reflect`]: crate::Reflect
174 fn try_serialize<S>(
175 &self,
176 value: &dyn PartialReflect,
177 registry: &TypeRegistry,
178 serializer: S,
179 ) -> Result<Result<S::Ok, S>, S::Error>
180 where
181 S: Serializer;
182}
183
184impl ReflectSerializerProcessor for () {
185 fn try_serialize<S>(
186 &self,
187 _value: &dyn PartialReflect,
188 _registry: &TypeRegistry,
189 serializer: S,
190 ) -> Result<Result<S::Ok, S>, S::Error>
191 where
192 S: Serializer,
193 {
194 Ok(Err(serializer))
195 }
196}