aldrin_core/introspection/
variant.rs

1use super::{ir, resolve_ir, LexicalId};
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 Variant {
16    id: u32,
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(rename = "type", default, skip_serializing_if = "Option::is_none")
28    )]
29    variant_type: Option<TypeId>,
30}
31
32impl Variant {
33    pub fn from_ir(ty: ir::VariantIr, references: &BTreeMap<LexicalId, TypeId>) -> Self {
34        Self {
35            id: ty.id,
36            name: ty.name,
37            doc: ty.doc,
38            variant_type: ty.variant_type.map(|ty| resolve_ir(ty, references)),
39        }
40    }
41
42    pub fn id(&self) -> u32 {
43        self.id
44    }
45
46    pub fn name(&self) -> &str {
47        &self.name
48    }
49
50    pub fn doc(&self) -> Option<&str> {
51        self.doc.as_deref()
52    }
53
54    pub fn variant_type(&self) -> Option<TypeId> {
55        self.variant_type
56    }
57}
58
59#[derive(IntoPrimitive, TryFromPrimitive)]
60#[repr(u32)]
61enum VariantField {
62    Id = 0,
63    Name = 1,
64    Doc = 2,
65    VariantType = 3,
66}
67
68impl Tag for Variant {}
69
70impl PrimaryTag for Variant {
71    type Tag = Self;
72}
73
74impl Serialize<Self> for Variant {
75    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
76        serializer.serialize(&self)
77    }
78}
79
80impl Serialize<Variant> for &Variant {
81    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
82        let mut serializer = serializer.serialize_struct2()?;
83
84        serializer.serialize::<tags::U32>(VariantField::Id, &self.id)?;
85        serializer.serialize::<tags::String>(VariantField::Name, &self.name)?;
86        serializer.serialize_if_some::<tags::Option<tags::String>>(VariantField::Doc, &self.doc)?;
87
88        serializer.serialize_if_some::<tags::Option<TypeId>>(
89            VariantField::VariantType,
90            &self.variant_type,
91        )?;
92
93        serializer.finish()
94    }
95}
96
97impl Deserialize<Self> for Variant {
98    fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
99        let mut deserializer = deserializer.deserialize_struct()?;
100
101        let mut id = None;
102        let mut name = None;
103        let mut doc = None;
104        let mut variant_type = None;
105
106        while let Some(deserializer) = deserializer.deserialize()? {
107            match deserializer.try_id() {
108                Ok(VariantField::Id) => {
109                    id = deserializer.deserialize::<tags::U32, _>().map(Some)?;
110                }
111
112                Ok(VariantField::Name) => {
113                    name = deserializer.deserialize::<tags::String, _>().map(Some)?;
114                }
115
116                Ok(VariantField::Doc) => {
117                    doc = deserializer.deserialize::<tags::Option<tags::String>, _>()?;
118                }
119
120                Ok(VariantField::VariantType) => {
121                    variant_type = deserializer.deserialize::<tags::Option<TypeId>, _>()?
122                }
123
124                Err(_) => deserializer.skip()?,
125            }
126        }
127
128        deserializer.finish(Self {
129            id: id.ok_or(DeserializeError::InvalidSerialization)?,
130            name: name.ok_or(DeserializeError::InvalidSerialization)?,
131            doc,
132            variant_type,
133        })
134    }
135}