Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/serde/de/processor.rs
6600 views
1
use crate::{PartialReflect, TypeRegistration, TypeRegistry};
2
use alloc::boxed::Box;
3
4
/// Allows overriding the default deserialization behavior of
5
/// [`ReflectDeserializer`] and [`TypedReflectDeserializer`] for specific
6
/// [`TypeRegistration`]s.
7
///
8
/// When deserializing a reflected value, you may want to override the default
9
/// behavior and use your own logic for deserialization. This logic may also
10
/// be context-dependent, and only apply for a single use of your
11
/// [`ReflectDeserializer`]. To achieve this, you can create a processor and
12
/// pass it in to your deserializer.
13
///
14
/// Whenever the deserializer attempts to deserialize a value, it will first
15
/// call [`try_deserialize`] on your processor, which may take ownership of the
16
/// deserializer and give back a [`Box<dyn PartialReflect>`], or return
17
/// ownership of the deserializer back, and continue with the default logic.
18
///
19
/// The serialization equivalent of this is [`ReflectSerializerProcessor`].
20
///
21
/// # Compared to [`DeserializeWithRegistry`]
22
///
23
/// [`DeserializeWithRegistry`] allows you to define how your type will be
24
/// deserialized by a [`TypedReflectDeserializer`], given the extra context of
25
/// the [`TypeRegistry`]. If your type can be deserialized entirely from that,
26
/// then 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 [`TypedReflectDeserializer`]. For example, in
30
/// an asset loader, the `&mut LoadContext` you get is only valid from within
31
/// the `load` function. This is where a processor is useful, as the processor
32
/// can capture local variables.
33
///
34
/// A [`ReflectDeserializerProcessor`] always takes priority over a
35
/// [`DeserializeWithRegistry`] implementation, so this is also useful for
36
/// overriding deserialization behavior if you need to do something custom.
37
///
38
/// # Examples
39
///
40
/// Deserializing a reflected value in an asset loader, and replacing asset
41
/// handles with a loaded equivalent:
42
///
43
/// ```
44
/// # use bevy_reflect::serde::{ReflectDeserializer, ReflectDeserializerProcessor};
45
/// # use bevy_reflect::{PartialReflect, Reflect, TypeData, TypeRegistration, TypeRegistry};
46
/// # use serde::de::{DeserializeSeed, Deserializer, Visitor};
47
/// # use std::marker::PhantomData;
48
/// #
49
/// # #[derive(Debug, Clone, Reflect)]
50
/// # struct LoadedUntypedAsset;
51
/// # #[derive(Debug, Clone, Reflect)]
52
/// # struct Handle<T: Reflect>(T);
53
/// # #[derive(Debug, Clone, Reflect)]
54
/// # struct Mesh;
55
/// #
56
/// # struct LoadContext;
57
/// # impl LoadContext {
58
/// # fn load(&mut self) -> &mut Self { unimplemented!() }
59
/// # fn with_asset_type_id(&mut self, (): ()) -> &mut Self { unimplemented!() }
60
/// # fn untyped(&mut self) -> &mut Self { unimplemented!() }
61
/// # fn load_asset(&mut self, (): ()) -> Handle<LoadedUntypedAsset> { unimplemented!() }
62
/// # }
63
/// #
64
/// # struct ReflectHandle;
65
/// # impl TypeData for ReflectHandle {
66
/// # fn clone_type_data(&self) -> Box<dyn TypeData> {
67
/// # unimplemented!()
68
/// # }
69
/// # }
70
/// # impl ReflectHandle {
71
/// # fn asset_type_id(&self) {
72
/// # unimplemented!()
73
/// # }
74
/// # }
75
/// #
76
/// # struct AssetPathVisitor;
77
/// # impl<'de> Visitor<'de> for AssetPathVisitor {
78
/// # type Value = ();
79
/// # fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { unimplemented!() }
80
/// # }
81
/// # type AssetError = Box<dyn core::error::Error>;
82
/// #[derive(Debug, Clone, Reflect)]
83
/// struct MyAsset {
84
/// name: String,
85
/// mesh: Handle<Mesh>,
86
/// }
87
///
88
/// fn load(
89
/// asset_bytes: &[u8],
90
/// type_registry: &TypeRegistry,
91
/// load_context: &mut LoadContext,
92
/// ) -> Result<MyAsset, AssetError> {
93
/// struct HandleProcessor<'a> {
94
/// load_context: &'a mut LoadContext,
95
/// }
96
///
97
/// impl ReflectDeserializerProcessor for HandleProcessor<'_> {
98
/// fn try_deserialize<'de, D>(
99
/// &mut self,
100
/// registration: &TypeRegistration,
101
/// _registry: &TypeRegistry,
102
/// deserializer: D,
103
/// ) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
104
/// where
105
/// D: Deserializer<'de>,
106
/// {
107
/// let Some(reflect_handle) = registration.data::<ReflectHandle>() else {
108
/// // we don't want to deserialize this - give the deserializer back
109
/// return Ok(Err(deserializer));
110
/// };
111
///
112
/// let asset_type_id = reflect_handle.asset_type_id();
113
/// let asset_path = deserializer.deserialize_str(AssetPathVisitor)?;
114
///
115
/// let handle: Handle<LoadedUntypedAsset> = self.load_context
116
/// .load()
117
/// .with_asset_type_id(asset_type_id)
118
/// .untyped()
119
/// .load_asset(asset_path);
120
/// # let _: Result<_, ()> = {
121
/// Ok(Box::new(handle))
122
/// # };
123
/// # unimplemented!()
124
/// }
125
/// }
126
///
127
/// let mut ron_deserializer = ron::Deserializer::from_bytes(asset_bytes)?;
128
/// let mut processor = HandleProcessor { load_context };
129
/// let reflect_deserializer =
130
/// ReflectDeserializer::with_processor(type_registry, &mut processor);
131
/// let asset = reflect_deserializer.deserialize(&mut ron_deserializer)?;
132
/// # unimplemented!()
133
/// }
134
/// ```
135
///
136
/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer
137
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
138
/// [`try_deserialize`]: Self::try_deserialize
139
/// [`DeserializeWithRegistry`]: crate::serde::DeserializeWithRegistry
140
/// [`ReflectSerializerProcessor`]: crate::serde::ReflectSerializerProcessor
141
pub trait ReflectDeserializerProcessor {
142
/// Attempts to deserialize the value which a [`TypedReflectDeserializer`]
143
/// is currently looking at, and knows the type of.
144
///
145
/// If you've read the `registration` and want to override the default
146
/// deserialization, return `Ok(Ok(value))` with the boxed reflected value
147
/// that you want to assign this value to. The type inside the box must
148
/// be the same one as the `registration` is for, otherwise future
149
/// reflection operations (such as using [`FromReflect`] to convert the
150
/// resulting [`Box<dyn PartialReflect>`] into a concrete type) will fail.
151
///
152
/// If you don't want to override the deserialization, return ownership of
153
/// the deserializer back via `Ok(Err(deserializer))`.
154
///
155
/// Note that, if you do want to return a value, you *must* read from the
156
/// deserializer passed to this function (you are free to ignore the result
157
/// though). Otherwise, the deserializer will be in an inconsistent state,
158
/// and future value parsing will fail.
159
///
160
/// # Examples
161
///
162
/// Correct way to return a constant value (not using any output from the
163
/// deserializer):
164
///
165
/// ```
166
/// # use bevy_reflect::{TypeRegistration, PartialReflect, TypeRegistry};
167
/// # use bevy_reflect::serde::ReflectDeserializerProcessor;
168
/// # use core::any::TypeId;
169
/// use serde::de::IgnoredAny;
170
///
171
/// struct ConstantI32Processor;
172
///
173
/// impl ReflectDeserializerProcessor for ConstantI32Processor {
174
/// fn try_deserialize<'de, D>(
175
/// &mut self,
176
/// registration: &TypeRegistration,
177
/// _registry: &TypeRegistry,
178
/// deserializer: D,
179
/// ) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
180
/// where
181
/// D: serde::Deserializer<'de>
182
/// {
183
/// if registration.type_id() == TypeId::of::<i32>() {
184
/// _ = deserializer.deserialize_ignored_any(IgnoredAny);
185
/// Ok(Ok(Box::new(42_i32)))
186
/// } else {
187
/// Ok(Err(deserializer))
188
/// }
189
/// }
190
/// }
191
/// ```
192
///
193
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
194
/// [`FromReflect`]: crate::FromReflect
195
fn try_deserialize<'de, D>(
196
&mut self,
197
registration: &TypeRegistration,
198
registry: &TypeRegistry,
199
deserializer: D,
200
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
201
where
202
D: serde::Deserializer<'de>;
203
}
204
205
impl ReflectDeserializerProcessor for () {
206
fn try_deserialize<'de, D>(
207
&mut self,
208
_registration: &TypeRegistration,
209
_registry: &TypeRegistry,
210
deserializer: D,
211
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>
212
where
213
D: serde::Deserializer<'de>,
214
{
215
Ok(Err(deserializer))
216
}
217
}
218
219