Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/serde/ser/serializer.rs
6600 views
1
#[cfg(feature = "debug_stack")]
2
use crate::serde::ser::error_utils::TYPE_INFO_STACK;
3
use crate::{
4
serde::ser::{
5
arrays::ArraySerializer, custom_serialization::try_custom_serialize, enums::EnumSerializer,
6
error_utils::make_custom_error, lists::ListSerializer, maps::MapSerializer,
7
sets::SetSerializer, structs::StructSerializer, tuple_structs::TupleStructSerializer,
8
tuples::TupleSerializer,
9
},
10
PartialReflect, ReflectRef, TypeRegistry,
11
};
12
use serde::{ser::SerializeMap, Serialize, Serializer};
13
14
use super::ReflectSerializerProcessor;
15
16
/// A general purpose serializer for reflected types.
17
///
18
/// This is the serializer counterpart to [`ReflectDeserializer`].
19
///
20
/// See [`TypedReflectSerializer`] for a serializer that serializes a known type.
21
///
22
/// # Output
23
///
24
/// This serializer will output a map with a single entry,
25
/// where the key is the _full_ [type path] of the reflected type
26
/// and the value is the serialized data.
27
///
28
/// If you want to override serialization for specific values, you can pass in
29
/// a reference to a [`ReflectSerializerProcessor`] which will take priority
30
/// over all other serialization methods - see [`with_processor`].
31
///
32
/// # Example
33
///
34
/// ```
35
/// # use bevy_reflect::prelude::*;
36
/// # use bevy_reflect::{TypeRegistry, serde::ReflectSerializer};
37
/// #[derive(Reflect, PartialEq, Debug)]
38
/// #[type_path = "my_crate"]
39
/// struct MyStruct {
40
/// value: i32
41
/// }
42
///
43
/// let mut registry = TypeRegistry::default();
44
/// registry.register::<MyStruct>();
45
///
46
/// let input = MyStruct { value: 123 };
47
///
48
/// let reflect_serializer = ReflectSerializer::new(&input, &registry);
49
/// let output = ron::to_string(&reflect_serializer).unwrap();
50
///
51
/// assert_eq!(output, r#"{"my_crate::MyStruct":(value:123)}"#);
52
/// ```
53
///
54
/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer
55
/// [type path]: crate::TypePath::type_path
56
/// [`with_processor`]: Self::with_processor
57
pub struct ReflectSerializer<'a, P = ()> {
58
value: &'a dyn PartialReflect,
59
registry: &'a TypeRegistry,
60
processor: Option<&'a P>,
61
}
62
63
impl<'a> ReflectSerializer<'a, ()> {
64
/// Creates a serializer with no processor.
65
///
66
/// If you want to add custom logic for serializing certain values, use
67
/// [`with_processor`].
68
///
69
/// [`with_processor`]: Self::with_processor
70
pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
71
Self {
72
value,
73
registry,
74
processor: None,
75
}
76
}
77
}
78
79
impl<'a, P: ReflectSerializerProcessor> ReflectSerializer<'a, P> {
80
/// Creates a serializer with a processor.
81
///
82
/// If you do not need any custom logic for handling certain values, use
83
/// [`new`].
84
///
85
/// [`new`]: Self::new
86
pub fn with_processor(
87
value: &'a dyn PartialReflect,
88
registry: &'a TypeRegistry,
89
processor: &'a P,
90
) -> Self {
91
Self {
92
value,
93
registry,
94
processor: Some(processor),
95
}
96
}
97
}
98
99
impl<P: ReflectSerializerProcessor> Serialize for ReflectSerializer<'_, P> {
100
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
101
where
102
S: Serializer,
103
{
104
let mut state = serializer.serialize_map(Some(1))?;
105
state.serialize_entry(
106
self.value
107
.get_represented_type_info()
108
.ok_or_else(|| {
109
if self.value.is_dynamic() {
110
make_custom_error(format_args!(
111
"cannot serialize dynamic value without represented type: `{}`",
112
self.value.reflect_type_path()
113
))
114
} else {
115
make_custom_error(format_args!(
116
"cannot get type info for `{}`",
117
self.value.reflect_type_path()
118
))
119
}
120
})?
121
.type_path(),
122
&TypedReflectSerializer::new_internal(self.value, self.registry, self.processor),
123
)?;
124
state.end()
125
}
126
}
127
128
/// A serializer for reflected types whose type will be known during deserialization.
129
///
130
/// This is the serializer counterpart to [`TypedReflectDeserializer`].
131
///
132
/// See [`ReflectSerializer`] for a serializer that serializes an unknown type.
133
///
134
/// # Output
135
///
136
/// Since the type is expected to be known during deserialization,
137
/// this serializer will not output any additional type information,
138
/// such as the [type path].
139
///
140
/// Instead, it will output just the serialized data.
141
///
142
/// If you want to override serialization for specific values, you can pass in
143
/// a reference to a [`ReflectSerializerProcessor`] which will take priority
144
/// over all other serialization methods - see [`with_processor`].
145
///
146
/// # Example
147
///
148
/// ```
149
/// # use bevy_reflect::prelude::*;
150
/// # use bevy_reflect::{TypeRegistry, serde::TypedReflectSerializer};
151
/// #[derive(Reflect, PartialEq, Debug)]
152
/// #[type_path = "my_crate"]
153
/// struct MyStruct {
154
/// value: i32
155
/// }
156
///
157
/// let mut registry = TypeRegistry::default();
158
/// registry.register::<MyStruct>();
159
///
160
/// let input = MyStruct { value: 123 };
161
///
162
/// let reflect_serializer = TypedReflectSerializer::new(&input, &registry);
163
/// let output = ron::to_string(&reflect_serializer).unwrap();
164
///
165
/// assert_eq!(output, r#"(value:123)"#);
166
/// ```
167
///
168
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
169
/// [type path]: crate::TypePath::type_path
170
/// [`with_processor`]: Self::with_processor
171
pub struct TypedReflectSerializer<'a, P = ()> {
172
value: &'a dyn PartialReflect,
173
registry: &'a TypeRegistry,
174
processor: Option<&'a P>,
175
}
176
177
impl<'a> TypedReflectSerializer<'a, ()> {
178
/// Creates a serializer with no processor.
179
///
180
/// If you want to add custom logic for serializing certain values, use
181
/// [`with_processor`].
182
///
183
/// [`with_processor`]: Self::with_processor
184
pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
185
#[cfg(feature = "debug_stack")]
186
TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());
187
188
Self {
189
value,
190
registry,
191
processor: None,
192
}
193
}
194
}
195
196
impl<'a, P> TypedReflectSerializer<'a, P> {
197
/// Creates a serializer with a processor.
198
///
199
/// If you do not need any custom logic for handling certain values, use
200
/// [`new`].
201
///
202
/// [`new`]: Self::new
203
pub fn with_processor(
204
value: &'a dyn PartialReflect,
205
registry: &'a TypeRegistry,
206
processor: &'a P,
207
) -> Self {
208
#[cfg(feature = "debug_stack")]
209
TYPE_INFO_STACK.set(crate::type_info_stack::TypeInfoStack::new());
210
211
Self {
212
value,
213
registry,
214
processor: Some(processor),
215
}
216
}
217
218
/// An internal constructor for creating a serializer without resetting the type info stack.
219
pub(super) fn new_internal(
220
value: &'a dyn PartialReflect,
221
registry: &'a TypeRegistry,
222
processor: Option<&'a P>,
223
) -> Self {
224
Self {
225
value,
226
registry,
227
processor,
228
}
229
}
230
}
231
232
impl<P: ReflectSerializerProcessor> Serialize for TypedReflectSerializer<'_, P> {
233
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
234
where
235
S: Serializer,
236
{
237
#[cfg(feature = "debug_stack")]
238
{
239
if let Some(info) = self.value.get_represented_type_info() {
240
TYPE_INFO_STACK.with_borrow_mut(|stack| stack.push(info));
241
}
242
}
243
244
// First, check if our processor wants to serialize this type
245
// This takes priority over any other serialization operations
246
let serializer = if let Some(processor) = self.processor {
247
match processor.try_serialize(self.value, self.registry, serializer) {
248
Ok(Ok(value)) => {
249
return Ok(value);
250
}
251
Err(err) => {
252
return Err(make_custom_error(err));
253
}
254
Ok(Err(serializer)) => serializer,
255
}
256
} else {
257
serializer
258
};
259
260
// Handle both Value case and types that have a custom `Serialize`
261
let (serializer, error) = match try_custom_serialize(self.value, self.registry, serializer)
262
{
263
Ok(result) => return result,
264
Err(value) => value,
265
};
266
267
let output = match self.value.reflect_ref() {
268
ReflectRef::Struct(struct_value) => StructSerializer {
269
struct_value,
270
registry: self.registry,
271
processor: self.processor,
272
}
273
.serialize(serializer),
274
ReflectRef::TupleStruct(tuple_struct) => TupleStructSerializer {
275
tuple_struct,
276
registry: self.registry,
277
processor: self.processor,
278
}
279
.serialize(serializer),
280
ReflectRef::Tuple(tuple) => TupleSerializer {
281
tuple,
282
registry: self.registry,
283
processor: self.processor,
284
}
285
.serialize(serializer),
286
ReflectRef::List(list) => ListSerializer {
287
list,
288
registry: self.registry,
289
processor: self.processor,
290
}
291
.serialize(serializer),
292
ReflectRef::Array(array) => ArraySerializer {
293
array,
294
registry: self.registry,
295
processor: self.processor,
296
}
297
.serialize(serializer),
298
ReflectRef::Map(map) => MapSerializer {
299
map,
300
registry: self.registry,
301
processor: self.processor,
302
}
303
.serialize(serializer),
304
ReflectRef::Set(set) => SetSerializer {
305
set,
306
registry: self.registry,
307
processor: self.processor,
308
}
309
.serialize(serializer),
310
ReflectRef::Enum(enum_value) => EnumSerializer {
311
enum_value,
312
registry: self.registry,
313
processor: self.processor,
314
}
315
.serialize(serializer),
316
#[cfg(feature = "functions")]
317
ReflectRef::Function(_) => Err(make_custom_error("functions cannot be serialized")),
318
ReflectRef::Opaque(_) => Err(error),
319
};
320
321
#[cfg(feature = "debug_stack")]
322
TYPE_INFO_STACK.with_borrow_mut(crate::type_info_stack::TypeInfoStack::pop);
323
324
output
325
}
326
}
327
328