aldrin_core/introspection/
enum_ty.rs

1use super::{ir, EnumFallback, LexicalId, Variant};
2use crate::tags::{self, PrimaryTag, Tag};
3use crate::{
4    Deserialize, DeserializeError, Deserializer, Serialize, SerializeError, Serializer, TypeId,
5};
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7use std::collections::BTreeMap;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(
11    feature = "serde",
12    derive(serde::Serialize, serde::Deserialize),
13    serde(rename_all = "kebab-case")
14)]
15pub struct Enum {
16    schema: String,
17    name: String,
18
19    #[cfg_attr(
20        feature = "serde",
21        serde(default, skip_serializing_if = "Option::is_none")
22    )]
23    doc: Option<String>,
24
25    #[cfg_attr(
26        feature = "serde",
27        serde(default, skip_serializing_if = "BTreeMap::is_empty")
28    )]
29    variants: BTreeMap<u32, Variant>,
30
31    #[cfg_attr(
32        feature = "serde",
33        serde(default, skip_serializing_if = "Option::is_none")
34    )]
35    fallback: Option<EnumFallback>,
36}
37
38impl Enum {
39    pub fn from_ir(ty: ir::EnumIr, references: &BTreeMap<LexicalId, TypeId>) -> Self {
40        Self {
41            schema: ty.schema,
42            name: ty.name,
43            doc: ty.doc,
44            variants: ty
45                .variants
46                .into_iter()
47                .map(|(id, var)| (id, Variant::from_ir(var, references)))
48                .collect(),
49            fallback: ty.fallback.map(EnumFallback::from_ir),
50        }
51    }
52
53    pub fn schema(&self) -> &str {
54        &self.schema
55    }
56
57    pub fn name(&self) -> &str {
58        &self.name
59    }
60
61    pub fn doc(&self) -> Option<&str> {
62        self.doc.as_deref()
63    }
64
65    pub fn variants(&self) -> &BTreeMap<u32, Variant> {
66        &self.variants
67    }
68
69    pub fn fallback(&self) -> Option<&EnumFallback> {
70        self.fallback.as_ref()
71    }
72}
73
74#[derive(IntoPrimitive, TryFromPrimitive)]
75#[repr(u32)]
76enum EnumField {
77    Schema = 0,
78    Name = 1,
79    Doc = 2,
80    Variants = 3,
81    Fallback = 4,
82}
83
84impl Tag for Enum {}
85
86impl PrimaryTag for Enum {
87    type Tag = Self;
88}
89
90impl Serialize<Self> for Enum {
91    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
92        serializer.serialize(&self)
93    }
94}
95
96impl Serialize<Enum> for &Enum {
97    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
98        let mut serializer = serializer.serialize_struct2()?;
99
100        serializer.serialize::<tags::String>(EnumField::Schema, &self.schema)?;
101        serializer.serialize::<tags::String>(EnumField::Name, &self.name)?;
102        serializer.serialize_if_some::<tags::Option<tags::String>>(EnumField::Doc, &self.doc)?;
103
104        serializer
105            .serialize::<tags::Map<tags::U32, Variant>>(EnumField::Variants, &self.variants)?;
106
107        serializer
108            .serialize_if_some::<tags::Option<EnumFallback>>(EnumField::Fallback, &self.fallback)?;
109
110        serializer.finish()
111    }
112}
113
114impl Deserialize<Self> for Enum {
115    fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
116        let mut deserializer = deserializer.deserialize_struct()?;
117
118        let mut schema = None;
119        let mut name = None;
120        let mut doc = None;
121        let mut variants = None;
122        let mut fallback = None;
123
124        while let Some(deserializer) = deserializer.deserialize()? {
125            match deserializer.try_id() {
126                Ok(EnumField::Schema) => {
127                    schema = deserializer.deserialize::<tags::String, _>().map(Some)?;
128                }
129
130                Ok(EnumField::Name) => {
131                    name = deserializer.deserialize::<tags::String, _>().map(Some)?;
132                }
133
134                Ok(EnumField::Doc) => {
135                    doc = deserializer.deserialize::<tags::Option<tags::String>, _>()?;
136                }
137
138                Ok(EnumField::Variants) => {
139                    variants = deserializer
140                        .deserialize::<tags::Map<tags::U32, Variant>, _>()
141                        .map(Some)?;
142                }
143
144                Ok(EnumField::Fallback) => {
145                    fallback = deserializer.deserialize::<tags::Option<EnumFallback>, _>()?;
146                }
147
148                Err(_) => deserializer.skip()?,
149            }
150        }
151
152        deserializer.finish(Self {
153            schema: schema.ok_or(DeserializeError::InvalidSerialization)?,
154            name: name.ok_or(DeserializeError::InvalidSerialization)?,
155            doc,
156            variants: variants.ok_or(DeserializeError::InvalidSerialization)?,
157            fallback,
158        })
159    }
160}