Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/serde/mod.rs
9367 views
1
//! Serde integration for reflected types.
2
3
mod de;
4
mod ser;
5
mod type_data;
6
7
pub use de::*;
8
pub use ser::*;
9
pub use type_data::*;
10
11
#[cfg(test)]
12
mod tests {
13
use super::*;
14
use crate::{
15
structs::{DynamicStruct, Struct},
16
tuple_struct::DynamicTupleStruct,
17
type_registry::TypeRegistry,
18
FromReflect, PartialReflect, Reflect,
19
};
20
use serde::de::DeserializeSeed;
21
22
#[test]
23
fn test_serialization_struct() {
24
#[derive(Debug, Reflect, PartialEq)]
25
#[reflect(PartialEq)]
26
struct TestStruct {
27
a: i32,
28
#[reflect(ignore)]
29
b: i32,
30
#[reflect(skip_serializing)]
31
c: i32,
32
#[reflect(skip_serializing)]
33
#[reflect(default = "custom_default")]
34
d: i32,
35
e: i32,
36
}
37
38
fn custom_default() -> i32 {
39
-1
40
}
41
42
let mut registry = TypeRegistry::default();
43
registry.register::<TestStruct>();
44
45
let test_struct = TestStruct {
46
a: 3,
47
b: 4,
48
c: 5,
49
d: 6,
50
e: 7,
51
};
52
53
let serializer = ReflectSerializer::new(&test_struct, &registry);
54
let serialized =
55
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
56
57
let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
58
let reflect_deserializer = ReflectDeserializer::new(&registry);
59
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
60
61
let mut expected = DynamicStruct::default();
62
expected.insert("a", 3);
63
// Ignored: expected.insert("b", 0);
64
expected.insert("c", 0);
65
expected.insert("d", -1);
66
expected.insert("e", 7);
67
68
assert!(
69
expected
70
.reflect_partial_eq(deserialized.as_partial_reflect())
71
.unwrap(),
72
"Deserialization failed: expected {expected:?} found {deserialized:?}"
73
);
74
75
let expected = TestStruct {
76
a: 3,
77
b: 0,
78
c: 0,
79
d: -1,
80
e: 7,
81
};
82
let received =
83
<TestStruct as FromReflect>::from_reflect(deserialized.as_partial_reflect()).unwrap();
84
85
assert_eq!(
86
expected, received,
87
"FromReflect failed: expected {expected:?} found {received:?}"
88
);
89
}
90
91
#[test]
92
fn test_serialization_tuple_struct() {
93
#[derive(Debug, Reflect, PartialEq)]
94
#[reflect(PartialEq)]
95
struct TestStruct(
96
i32,
97
#[reflect(ignore)] i32,
98
#[reflect(skip_serializing)] i32,
99
#[reflect(skip_serializing)]
100
#[reflect(default = "custom_default")]
101
i32,
102
i32,
103
);
104
105
fn custom_default() -> i32 {
106
-1
107
}
108
109
let mut registry = TypeRegistry::default();
110
registry.register::<TestStruct>();
111
112
let test_struct = TestStruct(3, 4, 5, 6, 7);
113
114
let serializer = ReflectSerializer::new(&test_struct, &registry);
115
let serialized =
116
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
117
118
let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
119
let reflect_deserializer = ReflectDeserializer::new(&registry);
120
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
121
122
let mut expected = DynamicTupleStruct::default();
123
expected.insert(3);
124
// Ignored: expected.insert(0);
125
expected.insert(0);
126
expected.insert(-1);
127
expected.insert(7);
128
129
assert!(
130
expected
131
.reflect_partial_eq(deserialized.as_partial_reflect())
132
.unwrap(),
133
"Deserialization failed: expected {expected:?} found {deserialized:?}"
134
);
135
136
let expected = TestStruct(3, 0, 0, -1, 7);
137
let received =
138
<TestStruct as FromReflect>::from_reflect(deserialized.as_partial_reflect()).unwrap();
139
140
assert_eq!(
141
expected, received,
142
"FromReflect failed: expected {expected:?} found {received:?}"
143
);
144
}
145
146
#[test]
147
#[should_panic(
148
expected = "cannot serialize dynamic value without represented type: `bevy_reflect::DynamicStruct`"
149
)]
150
fn should_not_serialize_unproxied_dynamic() {
151
let registry = TypeRegistry::default();
152
153
let mut value = DynamicStruct::default();
154
value.insert("foo", 123_u32);
155
156
let serializer = ReflectSerializer::new(&value, &registry);
157
ron::ser::to_string(&serializer).unwrap();
158
}
159
160
#[test]
161
fn should_roundtrip_proxied_dynamic() {
162
#[derive(Reflect)]
163
struct TestStruct {
164
a: i32,
165
b: i32,
166
}
167
168
let mut registry = TypeRegistry::default();
169
registry.register::<TestStruct>();
170
171
let value: DynamicStruct = TestStruct { a: 123, b: 456 }.to_dynamic_struct();
172
173
let serializer = ReflectSerializer::new(&value, &registry);
174
175
let expected = r#"{"bevy_reflect::serde::tests::TestStruct":(a:123,b:456)}"#;
176
let result = ron::ser::to_string(&serializer).unwrap();
177
assert_eq!(expected, result);
178
179
let mut deserializer = ron::de::Deserializer::from_str(&result).unwrap();
180
let reflect_deserializer = ReflectDeserializer::new(&registry);
181
182
let expected = value.to_dynamic();
183
let result = reflect_deserializer.deserialize(&mut deserializer).unwrap();
184
185
assert!(expected
186
.reflect_partial_eq(result.as_partial_reflect())
187
.unwrap());
188
}
189
190
mod type_data {
191
use super::*;
192
use crate::from_reflect::FromReflect;
193
use crate::serde::{DeserializeWithRegistry, ReflectDeserializeWithRegistry};
194
use crate::serde::{ReflectSerializeWithRegistry, SerializeWithRegistry};
195
use crate::{ReflectFromReflect, TypePath};
196
use alloc::{format, string::String, vec, vec::Vec};
197
use bevy_platform::sync::Arc;
198
use bevy_reflect_derive::reflect_trait;
199
use core::any::TypeId;
200
use core::fmt::{Debug, Formatter};
201
use serde::de::{SeqAccess, Visitor};
202
use serde::ser::SerializeSeq;
203
use serde::{Deserializer, Serialize, Serializer};
204
205
#[reflect_trait]
206
trait Enemy: Reflect + Debug {
207
#[expect(dead_code, reason = "this method is purely for testing purposes")]
208
fn hp(&self) -> u8;
209
}
210
211
// This is needed to support Arc<dyn Enemy>
212
impl TypePath for dyn Enemy {
213
fn type_path() -> &'static str {
214
"dyn bevy_reflect::serde::tests::type_data::Enemy"
215
}
216
217
fn short_type_path() -> &'static str {
218
"dyn Enemy"
219
}
220
}
221
222
#[derive(Reflect, Debug)]
223
#[reflect(Enemy)]
224
struct Skeleton(u8);
225
226
impl Enemy for Skeleton {
227
fn hp(&self) -> u8 {
228
self.0
229
}
230
}
231
232
#[derive(Reflect, Debug)]
233
#[reflect(Enemy)]
234
struct Zombie {
235
health: u8,
236
walk_speed: f32,
237
}
238
239
impl Enemy for Zombie {
240
fn hp(&self) -> u8 {
241
self.health
242
}
243
}
244
245
#[derive(Reflect, Debug)]
246
struct Level {
247
name: String,
248
enemies: EnemyList,
249
}
250
251
#[derive(Reflect, Debug)]
252
#[reflect(SerializeWithRegistry, DeserializeWithRegistry)]
253
// Note that we have to use `Arc` instead of `Box` here due to the
254
// former being the only one between the two to implement `Reflect`.
255
struct EnemyList(Vec<Arc<dyn Enemy>>);
256
257
impl SerializeWithRegistry for EnemyList {
258
fn serialize<S>(
259
&self,
260
serializer: S,
261
registry: &TypeRegistry,
262
) -> Result<S::Ok, S::Error>
263
where
264
S: Serializer,
265
{
266
let mut state = serializer.serialize_seq(Some(self.0.len()))?;
267
for enemy in &self.0 {
268
state.serialize_element(&ReflectSerializer::new(
269
(**enemy).as_partial_reflect(),
270
registry,
271
))?;
272
}
273
state.end()
274
}
275
}
276
277
impl<'de> DeserializeWithRegistry<'de> for EnemyList {
278
fn deserialize<D>(deserializer: D, registry: &TypeRegistry) -> Result<Self, D::Error>
279
where
280
D: Deserializer<'de>,
281
{
282
struct EnemyListVisitor<'a> {
283
registry: &'a TypeRegistry,
284
}
285
286
impl<'a, 'de> Visitor<'de> for EnemyListVisitor<'a> {
287
type Value = Vec<Arc<dyn Enemy>>;
288
289
fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
290
write!(formatter, "a list of enemies")
291
}
292
293
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
294
where
295
A: SeqAccess<'de>,
296
{
297
let mut enemies = Vec::new();
298
while let Some(enemy) =
299
seq.next_element_seed(ReflectDeserializer::new(self.registry))?
300
{
301
let registration = self
302
.registry
303
.get_with_type_path(
304
enemy.get_represented_type_info().unwrap().type_path(),
305
)
306
.unwrap();
307
308
// 1. Convert any possible dynamic values to concrete ones
309
let enemy = registration
310
.data::<ReflectFromReflect>()
311
.unwrap()
312
.from_reflect(&*enemy)
313
.unwrap();
314
315
// 2. Convert the concrete value to a boxed trait object
316
let enemy = registration
317
.data::<ReflectEnemy>()
318
.unwrap()
319
.get_boxed(enemy)
320
.unwrap();
321
322
enemies.push(enemy.into());
323
}
324
325
Ok(enemies)
326
}
327
}
328
329
deserializer
330
.deserialize_seq(EnemyListVisitor { registry })
331
.map(EnemyList)
332
}
333
}
334
335
fn create_registry() -> TypeRegistry {
336
let mut registry = TypeRegistry::default();
337
registry.register::<Level>();
338
registry.register::<EnemyList>();
339
registry.register::<Skeleton>();
340
registry.register::<Zombie>();
341
registry
342
}
343
344
fn create_arc_dyn_enemy<T: Enemy>(enemy: T) -> Arc<dyn Enemy> {
345
let arc = Arc::new(enemy);
346
347
#[cfg(not(target_has_atomic = "ptr"))]
348
#[expect(
349
unsafe_code,
350
reason = "unsized coercion is an unstable feature for non-std types"
351
)]
352
// SAFETY:
353
// - Coercion from `T` to `dyn Enemy` is valid as `T: Enemy + 'static`
354
// - `Arc::from_raw` receives a valid pointer from a previous call to `Arc::into_raw`
355
let arc = unsafe { Arc::from_raw(Arc::into_raw(arc) as *const dyn Enemy) };
356
357
arc
358
}
359
360
#[test]
361
fn should_serialize_with_serialize_with_registry() {
362
let registry = create_registry();
363
364
let level = Level {
365
name: String::from("Level 1"),
366
enemies: EnemyList(vec![
367
create_arc_dyn_enemy(Skeleton(10)),
368
create_arc_dyn_enemy(Zombie {
369
health: 20,
370
walk_speed: 0.5,
371
}),
372
]),
373
};
374
375
let serializer = ReflectSerializer::new(&level, &registry);
376
let serialized = ron::ser::to_string(&serializer).unwrap();
377
378
let expected = r#"{"bevy_reflect::serde::tests::type_data::Level":(name:"Level 1",enemies:[{"bevy_reflect::serde::tests::type_data::Skeleton":(10)},{"bevy_reflect::serde::tests::type_data::Zombie":(health:20,walk_speed:0.5)}])}"#;
379
380
assert_eq!(expected, serialized);
381
}
382
383
#[test]
384
fn should_deserialize_with_deserialize_with_registry() {
385
let registry = create_registry();
386
387
let input = r#"{"bevy_reflect::serde::tests::type_data::Level":(name:"Level 1",enemies:[{"bevy_reflect::serde::tests::type_data::Skeleton":(10)},{"bevy_reflect::serde::tests::type_data::Zombie":(health:20,walk_speed:0.5)}])}"#;
388
389
let mut deserializer = ron::de::Deserializer::from_str(input).unwrap();
390
let reflect_deserializer = ReflectDeserializer::new(&registry);
391
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
392
393
let output = Level::from_reflect(&*value).unwrap();
394
395
let expected = Level {
396
name: String::from("Level 1"),
397
enemies: EnemyList(vec![
398
create_arc_dyn_enemy(Skeleton(10)),
399
create_arc_dyn_enemy(Zombie {
400
health: 20,
401
walk_speed: 0.5,
402
}),
403
]),
404
};
405
406
// Poor man's comparison since we can't derive PartialEq for Arc<dyn Enemy>
407
assert_eq!(format!("{expected:?}"), format!("{output:?}",));
408
409
let unexpected = Level {
410
name: String::from("Level 1"),
411
enemies: EnemyList(vec![
412
create_arc_dyn_enemy(Skeleton(20)),
413
create_arc_dyn_enemy(Zombie {
414
health: 20,
415
walk_speed: 5.0,
416
}),
417
]),
418
};
419
420
// Poor man's comparison since we can't derive PartialEq for Arc<dyn Enemy>
421
assert_ne!(format!("{unexpected:?}"), format!("{output:?}"));
422
}
423
424
#[test]
425
fn should_serialize_single_tuple_struct_as_newtype() {
426
#[derive(Reflect, Serialize, PartialEq, Debug)]
427
struct TupleStruct(u32);
428
429
#[derive(Reflect, Serialize, PartialEq, Debug)]
430
struct TupleStructWithSkip(
431
u32,
432
#[reflect(skip_serializing)]
433
#[serde(skip)]
434
u32,
435
);
436
437
#[derive(Reflect, Serialize, PartialEq, Debug)]
438
enum Enum {
439
TupleStruct(usize),
440
NestedTupleStruct(TupleStruct),
441
NestedTupleStructWithSkip(TupleStructWithSkip),
442
}
443
444
let mut registry = TypeRegistry::default();
445
registry.register::<TupleStruct>();
446
registry.register::<TupleStructWithSkip>();
447
registry.register::<Enum>();
448
449
let tuple_struct = TupleStruct(1);
450
let tuple_struct_with_skip = TupleStructWithSkip(2, 3);
451
let tuple_struct_enum = Enum::TupleStruct(4);
452
let nested_tuple_struct = Enum::NestedTupleStruct(TupleStruct(5));
453
let nested_tuple_struct_with_skip =
454
Enum::NestedTupleStructWithSkip(TupleStructWithSkip(6, 7));
455
456
fn assert_serialize<T: Reflect + FromReflect + Serialize + PartialEq + Debug>(
457
value: &T,
458
registry: &TypeRegistry,
459
) {
460
let serializer = TypedReflectSerializer::new(value, registry);
461
let reflect_serialize = serde_json::to_string(&serializer).unwrap();
462
let serde_serialize = serde_json::to_string(value).unwrap();
463
assert_eq!(reflect_serialize, serde_serialize);
464
465
let registration = registry.get(TypeId::of::<T>()).unwrap();
466
let reflect_deserializer = TypedReflectDeserializer::new(registration, registry);
467
468
let mut deserializer = serde_json::Deserializer::from_str(&serde_serialize);
469
let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
470
let _ = T::from_reflect(&*reflect_value).unwrap();
471
}
472
473
assert_serialize(&tuple_struct, &registry);
474
assert_serialize(&tuple_struct_with_skip, &registry);
475
assert_serialize(&tuple_struct_enum, &registry);
476
assert_serialize(&nested_tuple_struct, &registry);
477
assert_serialize(&nested_tuple_struct_with_skip, &registry);
478
}
479
}
480
}
481
482