Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/serde/ser/enums.rs
9440 views
1
use crate::{
2
enums::{Enum, VariantInfo, VariantType},
3
serde::{ser::error_utils::make_custom_error, TypedReflectSerializer},
4
TypeInfo, TypeRegistry,
5
};
6
use serde::{
7
ser::{SerializeStructVariant, SerializeTupleVariant},
8
Serialize,
9
};
10
11
use super::ReflectSerializerProcessor;
12
13
/// A serializer for [`Enum`] values.
14
pub(super) struct EnumSerializer<'a, P> {
15
pub enum_value: &'a dyn Enum,
16
pub registry: &'a TypeRegistry,
17
pub processor: Option<&'a P>,
18
}
19
20
impl<P: ReflectSerializerProcessor> Serialize for EnumSerializer<'_, P> {
21
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
22
where
23
S: serde::Serializer,
24
{
25
let type_info = self.enum_value.get_represented_type_info().ok_or_else(|| {
26
make_custom_error(format_args!(
27
"cannot get type info for `{}`",
28
self.enum_value.reflect_type_path()
29
))
30
})?;
31
32
let enum_info = match type_info {
33
TypeInfo::Enum(enum_info) => enum_info,
34
info => {
35
return Err(make_custom_error(format_args!(
36
"expected enum type but received {info:?}"
37
)));
38
}
39
};
40
41
let enum_name = enum_info.type_path_table().ident().unwrap();
42
let variant_index = self.enum_value.variant_index() as u32;
43
let variant_info = enum_info
44
.variant_at(variant_index as usize)
45
.ok_or_else(|| {
46
make_custom_error(format_args!(
47
"variant at index `{variant_index}` does not exist",
48
))
49
})?;
50
let variant_name = variant_info.name();
51
let variant_type = self.enum_value.variant_type();
52
let field_len = self.enum_value.field_len();
53
54
match variant_type {
55
VariantType::Unit => {
56
if type_info.type_path_table().module_path() == Some("core::option")
57
&& type_info.type_path_table().ident() == Some("Option")
58
{
59
serializer.serialize_none()
60
} else {
61
serializer.serialize_unit_variant(enum_name, variant_index, variant_name)
62
}
63
}
64
VariantType::Struct => {
65
let struct_info = match variant_info {
66
VariantInfo::Struct(struct_info) => struct_info,
67
info => {
68
return Err(make_custom_error(format_args!(
69
"expected struct variant type but received {info:?}",
70
)));
71
}
72
};
73
74
let mut state = serializer.serialize_struct_variant(
75
enum_name,
76
variant_index,
77
variant_name,
78
field_len,
79
)?;
80
for (index, field) in self.enum_value.iter_fields().enumerate() {
81
let field_info = struct_info.field_at(index).unwrap();
82
state.serialize_field(
83
field_info.name(),
84
&TypedReflectSerializer::new_internal(
85
field.value(),
86
self.registry,
87
self.processor,
88
),
89
)?;
90
}
91
state.end()
92
}
93
VariantType::Tuple if field_len == 1 => {
94
let field = self.enum_value.field_at(0).unwrap();
95
96
if type_info.type_path_table().module_path() == Some("core::option")
97
&& type_info.type_path_table().ident() == Some("Option")
98
{
99
serializer.serialize_some(&TypedReflectSerializer::new_internal(
100
field,
101
self.registry,
102
self.processor,
103
))
104
} else {
105
serializer.serialize_newtype_variant(
106
enum_name,
107
variant_index,
108
variant_name,
109
&TypedReflectSerializer::new_internal(field, self.registry, self.processor),
110
)
111
}
112
}
113
VariantType::Tuple => {
114
let mut state = serializer.serialize_tuple_variant(
115
enum_name,
116
variant_index,
117
variant_name,
118
field_len,
119
)?;
120
for field in self.enum_value.iter_fields() {
121
state.serialize_field(&TypedReflectSerializer::new_internal(
122
field.value(),
123
self.registry,
124
self.processor,
125
))?;
126
}
127
state.end()
128
}
129
}
130
}
131
}
132
133