bevy_reflect/serde/ser/
enums.rs

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