aldrin_core/introspection/
field.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 Field {
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(feature = "serde", serde(rename = "required"))]
26    is_required: bool,
27
28    field_type: TypeId,
29}
30
31impl Field {
32    pub fn from_ir(ty: ir::FieldIr, references: &BTreeMap<LexicalId, TypeId>) -> Self {
33        Self {
34            id: ty.id,
35            name: ty.name,
36            doc: ty.doc,
37            is_required: ty.is_required,
38            field_type: resolve_ir(ty.field_type, 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 is_required(&self) -> bool {
55        self.is_required
56    }
57
58    pub fn field_type(&self) -> TypeId {
59        self.field_type
60    }
61}
62
63#[derive(IntoPrimitive, TryFromPrimitive)]
64#[repr(u32)]
65enum FieldField {
66    Id = 0,
67    Name = 1,
68    Doc = 2,
69    IsRequired = 3,
70    FieldType = 4,
71}
72
73impl Tag for Field {}
74
75impl PrimaryTag for Field {
76    type Tag = Self;
77}
78
79impl Serialize<Self> for Field {
80    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
81        serializer.serialize(&self)
82    }
83}
84
85impl Serialize<Field> for &Field {
86    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
87        let mut serializer = serializer.serialize_struct2()?;
88
89        serializer.serialize::<tags::U32>(FieldField::Id, &self.id)?;
90        serializer.serialize::<tags::String>(FieldField::Name, &self.name)?;
91        serializer.serialize_if_some::<tags::Option<tags::String>>(FieldField::Doc, &self.doc)?;
92        serializer.serialize::<tags::Bool>(FieldField::IsRequired, &self.is_required)?;
93        serializer.serialize::<TypeId>(FieldField::FieldType, &self.field_type)?;
94
95        serializer.finish()
96    }
97}
98
99impl Deserialize<Self> for Field {
100    fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
101        let mut deserializer = deserializer.deserialize_struct()?;
102
103        let mut id = None;
104        let mut name = None;
105        let mut doc = None;
106        let mut is_required = None;
107        let mut field_type = None;
108
109        while let Some(deserializer) = deserializer.deserialize()? {
110            match deserializer.try_id() {
111                Ok(FieldField::Id) => id = deserializer.deserialize::<tags::U32, _>().map(Some)?,
112
113                Ok(FieldField::Name) => {
114                    name = deserializer.deserialize::<tags::String, _>().map(Some)?;
115                }
116
117                Ok(FieldField::Doc) => {
118                    doc = deserializer.deserialize::<tags::Option<tags::String>, _>()?;
119                }
120
121                Ok(FieldField::IsRequired) => {
122                    is_required = deserializer.deserialize::<tags::Bool, _>().map(Some)?;
123                }
124
125                Ok(FieldField::FieldType) => {
126                    field_type = deserializer.deserialize::<TypeId, _>().map(Some)?;
127                }
128
129                Err(_) => deserializer.skip()?,
130            }
131        }
132
133        deserializer.finish(Self {
134            id: id.ok_or(DeserializeError::InvalidSerialization)?,
135            name: name.ok_or(DeserializeError::InvalidSerialization)?,
136            doc,
137            is_required: is_required.ok_or(DeserializeError::InvalidSerialization)?,
138            field_type: field_type.ok_or(DeserializeError::InvalidSerialization)?,
139        })
140    }
141}