aldrin_core/introspection/
service.rs

1use super::{ir, Event, EventFallback, Function, FunctionFallback, LexicalId};
2use crate::tags::{self, PrimaryTag, Tag};
3use crate::{
4    Deserialize, DeserializeError, Deserializer, Serialize, SerializeError, Serializer,
5    ServiceUuid, TypeId,
6};
7use num_enum::{IntoPrimitive, TryFromPrimitive};
8use std::collections::BTreeMap;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11#[cfg_attr(
12    feature = "serde",
13    derive(serde::Serialize, serde::Deserialize),
14    serde(rename_all = "kebab-case")
15)]
16pub struct Service {
17    schema: String,
18    name: String,
19
20    #[cfg_attr(
21        feature = "serde",
22        serde(default, skip_serializing_if = "Option::is_none")
23    )]
24    doc: Option<String>,
25    uuid: ServiceUuid,
26    version: u32,
27
28    #[cfg_attr(
29        feature = "serde",
30        serde(default, skip_serializing_if = "BTreeMap::is_empty")
31    )]
32    functions: BTreeMap<u32, Function>,
33
34    #[cfg_attr(
35        feature = "serde",
36        serde(default, skip_serializing_if = "BTreeMap::is_empty")
37    )]
38    events: BTreeMap<u32, Event>,
39
40    #[cfg_attr(
41        feature = "serde",
42        serde(default, skip_serializing_if = "Option::is_none")
43    )]
44    function_fallback: Option<FunctionFallback>,
45
46    #[cfg_attr(
47        feature = "serde",
48        serde(default, skip_serializing_if = "Option::is_none")
49    )]
50    event_fallback: Option<EventFallback>,
51}
52
53impl Service {
54    pub fn from_ir(ty: ir::ServiceIr, references: &BTreeMap<LexicalId, TypeId>) -> Self {
55        Self {
56            schema: ty.schema,
57            name: ty.name,
58            doc: ty.doc,
59            uuid: ty.uuid,
60            version: ty.version,
61
62            functions: ty
63                .functions
64                .into_iter()
65                .map(|(id, func)| (id, Function::from_ir(func, references)))
66                .collect(),
67
68            events: ty
69                .events
70                .into_iter()
71                .map(|(id, ev)| (id, Event::from_ir(ev, references)))
72                .collect(),
73
74            function_fallback: ty.function_fallback.map(FunctionFallback::from_ir),
75            event_fallback: ty.event_fallback.map(EventFallback::from_ir),
76        }
77    }
78
79    pub fn schema(&self) -> &str {
80        &self.schema
81    }
82
83    pub fn name(&self) -> &str {
84        &self.name
85    }
86
87    pub fn doc(&self) -> Option<&str> {
88        self.doc.as_deref()
89    }
90
91    pub fn uuid(&self) -> ServiceUuid {
92        self.uuid
93    }
94
95    pub fn version(&self) -> u32 {
96        self.version
97    }
98
99    pub fn functions(&self) -> &BTreeMap<u32, Function> {
100        &self.functions
101    }
102
103    pub fn events(&self) -> &BTreeMap<u32, Event> {
104        &self.events
105    }
106
107    pub fn function_fallback(&self) -> Option<&FunctionFallback> {
108        self.function_fallback.as_ref()
109    }
110
111    pub fn event_fallback(&self) -> Option<&EventFallback> {
112        self.event_fallback.as_ref()
113    }
114}
115
116#[derive(IntoPrimitive, TryFromPrimitive)]
117#[repr(u32)]
118enum ServiceField {
119    Schema = 0,
120    Name = 1,
121    Doc = 2,
122    Uuid = 3,
123    Version = 4,
124    Functions = 5,
125    Events = 6,
126    FunctionFallback = 7,
127    EventFallback = 8,
128}
129
130impl Tag for Service {}
131
132impl PrimaryTag for Service {
133    type Tag = Self;
134}
135
136impl Serialize<Self> for Service {
137    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
138        serializer.serialize(&self)
139    }
140}
141
142impl Serialize<Service> for &Service {
143    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
144        let mut serializer = serializer.serialize_struct2()?;
145
146        serializer.serialize::<tags::String>(ServiceField::Schema, &self.schema)?;
147        serializer.serialize::<tags::String>(ServiceField::Name, &self.name)?;
148        serializer.serialize_if_some::<tags::Option<tags::String>>(ServiceField::Doc, &self.doc)?;
149        serializer.serialize::<ServiceUuid>(ServiceField::Uuid, &self.uuid)?;
150        serializer.serialize::<tags::U32>(ServiceField::Version, &self.version)?;
151
152        serializer.serialize::<tags::Map<tags::U32, Function>>(
153            ServiceField::Functions,
154            &self.functions,
155        )?;
156
157        serializer.serialize::<tags::Map<tags::U32, Event>>(ServiceField::Events, &self.events)?;
158
159        serializer.serialize_if_some::<tags::Option<FunctionFallback>>(
160            ServiceField::FunctionFallback,
161            &self.function_fallback,
162        )?;
163
164        serializer.serialize_if_some::<tags::Option<EventFallback>>(
165            ServiceField::EventFallback,
166            &self.event_fallback,
167        )?;
168
169        serializer.finish()
170    }
171}
172
173impl Deserialize<Self> for Service {
174    fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
175        let mut deserializer = deserializer.deserialize_struct()?;
176
177        let mut schema = None;
178        let mut name = None;
179        let mut doc = None;
180        let mut uuid = None;
181        let mut version = None;
182        let mut functions = None;
183        let mut events = None;
184        let mut function_fallback = None;
185        let mut event_fallback = None;
186
187        while let Some(deserializer) = deserializer.deserialize()? {
188            match deserializer.try_id() {
189                Ok(ServiceField::Schema) => {
190                    schema = deserializer.deserialize::<tags::String, _>().map(Some)?;
191                }
192
193                Ok(ServiceField::Name) => {
194                    name = deserializer.deserialize::<tags::String, _>().map(Some)?;
195                }
196
197                Ok(ServiceField::Doc) => {
198                    doc = deserializer.deserialize::<tags::Option<tags::String>, _>()?;
199                }
200
201                Ok(ServiceField::Uuid) => {
202                    uuid = deserializer.deserialize::<ServiceUuid, _>().map(Some)?;
203                }
204
205                Ok(ServiceField::Version) => {
206                    version = deserializer.deserialize::<tags::U32, _>().map(Some)?;
207                }
208
209                Ok(ServiceField::Functions) => {
210                    functions = deserializer
211                        .deserialize::<tags::Map<tags::U32, Function>, _>()
212                        .map(Some)?;
213                }
214
215                Ok(ServiceField::Events) => {
216                    events = deserializer
217                        .deserialize::<tags::Map<tags::U32, Event>, _>()
218                        .map(Some)?;
219                }
220
221                Ok(ServiceField::FunctionFallback) => {
222                    function_fallback =
223                        deserializer.deserialize::<tags::Option<FunctionFallback>, _>()?;
224                }
225
226                Ok(ServiceField::EventFallback) => {
227                    event_fallback =
228                        deserializer.deserialize::<tags::Option<EventFallback>, _>()?;
229                }
230
231                Err(_) => deserializer.skip()?,
232            }
233        }
234
235        deserializer.finish(Self {
236            schema: schema.ok_or(DeserializeError::InvalidSerialization)?,
237            name: name.ok_or(DeserializeError::InvalidSerialization)?,
238            doc,
239            uuid: uuid.ok_or(DeserializeError::InvalidSerialization)?,
240            version: version.ok_or(DeserializeError::InvalidSerialization)?,
241            functions: functions.ok_or(DeserializeError::InvalidSerialization)?,
242            events: events.ok_or(DeserializeError::InvalidSerialization)?,
243            function_fallback,
244            event_fallback,
245        })
246    }
247}