Skip to main content

bevy_reflect/serde/ser/
enums.rs

1use crate::{
2    enums::{Enum, VariantInfo, VariantType},
3    serde::{ser::error_utils::make_custom_error, TypedReflectSerializer},
4    TypeInfo, TypeRegistry,
5};
6use serde::{
7    ser::{SerializeStructVariant, SerializeTupleVariant},
8    Serialize,
9};
10
11use super::ReflectSerializerProcessor;
12
13/// A serializer for [`Enum`] values.
14pub(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
20impl<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}