aldrin_core/introspection/
struct_ty.rs1use super::{Field, LexicalId};
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 Struct {
11 schema: String,
12 name: String,
13 fields: BTreeMap<u32, Field>,
14 fallback: Option<String>,
15}
16
17impl Struct {
18 pub const NAMESPACE: Uuid = uuid!("83742d78-4e60-44b2-84e7-75904c5987c1");
19
20 pub fn builder(schema: impl Into<String>, name: impl Into<String>) -> StructBuilder {
21 StructBuilder::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 fields(&self) -> &BTreeMap<u32, Field> {
37 &self.fields
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 StructField {
48 Schema = 0,
49 Name = 1,
50 Fields = 2,
51 Fallback = 3,
52}
53
54impl Serialize for Struct {
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(StructField::Schema, &self.schema)?;
60 serializer.serialize_field(StructField::Name, &self.name)?;
61 serializer.serialize_field(StructField::Fields, &self.fields)?;
62
63 if self.fallback.is_some() {
64 serializer.serialize_field(StructField::Fallback, &self.fallback)?;
65 }
66
67 serializer.finish()
68 }
69}
70
71impl Deserialize for Struct {
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 fields = 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 StructField::Schema => schema = deserializer.deserialize().map(Some)?,
85 StructField::Name => name = deserializer.deserialize().map(Some)?,
86 StructField::Fields => fields = deserializer.deserialize().map(Some)?,
87 StructField::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 fields: fields.ok_or(DeserializeError::InvalidSerialization)?,
95 fallback,
96 })
97 }
98}
99
100#[derive(Debug, Clone)]
101pub struct StructBuilder {
102 schema: String,
103 name: String,
104 fields: BTreeMap<u32, Field>,
105 fallback: Option<String>,
106}
107
108impl StructBuilder {
109 pub fn new(schema: impl Into<String>, name: impl Into<String>) -> Self {
110 Self {
111 schema: schema.into(),
112 name: name.into(),
113 fields: BTreeMap::new(),
114 fallback: None,
115 }
116 }
117
118 pub fn field(
119 mut self,
120 id: u32,
121 name: impl Into<String>,
122 is_required: bool,
123 field_type: LexicalId,
124 ) -> Self {
125 self.fields
126 .insert(id, Field::new(id, name, is_required, field_type));
127 self
128 }
129
130 pub fn fallback(mut self, name: impl Into<String>) -> Self {
131 self.fallback = Some(name.into());
132 self
133 }
134
135 pub fn finish(self) -> Struct {
136 Struct {
137 schema: self.schema,
138 name: self.name,
139 fields: self.fields,
140 fallback: self.fallback,
141 }
142 }
143}