aldrin_core/introspection/
enum_ty.rs1use 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}