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}