aldrin_core/introspection/
enum_ty.rs

1use super::{LexicalId, Variant};
2use crate::error::{DeserializeError, SerializeError};
3use crate::value_deserializer::{Deserialize, Deserializer};
4use crate::value_serializer::{Serialize, Serializer};
5use num_enum::{IntoPrimitive, TryFromPrimitive};
6use std::collections::BTreeMap;
7use uuid::{uuid, Uuid};
8
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct Enum {
11    schema: String,
12    name: String,
13    variants: BTreeMap<u32, Variant>,
14    fallback: Option<String>,
15}
16
17impl Enum {
18    pub const NAMESPACE: Uuid = uuid!("642bf73e-991f-406a-b55a-ce914d77480b");
19
20    pub fn builder(schema: impl Into<String>, name: impl Into<String>) -> EnumBuilder {
21        EnumBuilder::new(schema, name)
22    }
23
24    pub fn lexical_id(&self) -> LexicalId {
25        LexicalId::custom(&self.schema, &self.name)
26    }
27
28    pub fn schema(&self) -> &str {
29        &self.schema
30    }
31
32    pub fn name(&self) -> &str {
33        &self.name
34    }
35
36    pub fn variants(&self) -> &BTreeMap<u32, Variant> {
37        &self.variants
38    }
39
40    pub fn fallback(&self) -> Option<&str> {
41        self.fallback.as_deref()
42    }
43}
44
45#[derive(IntoPrimitive, TryFromPrimitive)]
46#[repr(u32)]
47enum EnumField {
48    Schema = 0,
49    Name = 1,
50    Variants = 2,
51    Fallback = 3,
52}
53
54impl Serialize for Enum {
55    fn serialize(&self, serializer: Serializer) -> Result<(), SerializeError> {
56        let num = 3 + (self.fallback.is_some() as usize);
57        let mut serializer = serializer.serialize_struct(num)?;
58
59        serializer.serialize_field(EnumField::Schema, &self.schema)?;
60        serializer.serialize_field(EnumField::Name, &self.name)?;
61        serializer.serialize_field(EnumField::Variants, &self.variants)?;
62
63        if let Some(ref fallback) = self.fallback {
64            serializer.serialize_field(EnumField::Fallback, &Some(fallback))?;
65        }
66
67        serializer.finish()
68    }
69}
70
71impl Deserialize for Enum {
72    fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
73        let mut deserializer = deserializer.deserialize_struct()?;
74
75        let mut schema = None;
76        let mut name = None;
77        let mut variants = None;
78        let mut fallback = None;
79
80        while deserializer.has_more_fields() {
81            let deserializer = deserializer.deserialize_field()?;
82
83            match deserializer.try_id()? {
84                EnumField::Schema => schema = deserializer.deserialize().map(Some)?,
85                EnumField::Name => name = deserializer.deserialize().map(Some)?,
86                EnumField::Variants => variants = deserializer.deserialize().map(Some)?,
87                EnumField::Fallback => fallback = deserializer.deserialize()?,
88            }
89        }
90
91        deserializer.finish(Self {
92            schema: schema.ok_or(DeserializeError::InvalidSerialization)?,
93            name: name.ok_or(DeserializeError::InvalidSerialization)?,
94            variants: variants.ok_or(DeserializeError::InvalidSerialization)?,
95            fallback,
96        })
97    }
98}
99
100#[derive(Debug, Clone)]
101pub struct EnumBuilder {
102    schema: String,
103    name: String,
104    variants: BTreeMap<u32, Variant>,
105    fallback: Option<String>,
106}
107
108impl EnumBuilder {
109    pub fn new(schema: impl Into<String>, name: impl Into<String>) -> Self {
110        Self {
111            schema: schema.into(),
112            name: name.into(),
113            variants: BTreeMap::new(),
114            fallback: None,
115        }
116    }
117
118    pub fn variant(
119        mut self,
120        id: u32,
121        name: impl Into<String>,
122        variant_type: Option<LexicalId>,
123    ) -> Self {
124        self.variants
125            .insert(id, Variant::new(id, name, variant_type));
126        self
127    }
128
129    pub fn variant_with_type(
130        self,
131        id: u32,
132        name: impl Into<String>,
133        variant_type: LexicalId,
134    ) -> Self {
135        self.variant(id, name, Some(variant_type))
136    }
137
138    pub fn unit_variant(self, id: u32, name: impl Into<String>) -> Self {
139        self.variant(id, name, None)
140    }
141
142    pub fn fallback(mut self, name: impl Into<String>) -> Self {
143        self.fallback = Some(name.into());
144        self
145    }
146
147    pub fn finish(self) -> Enum {
148        Enum {
149            schema: self.schema,
150            name: self.name,
151            variants: self.variants,
152            fallback: self.fallback,
153        }
154    }
155}