aldrin_core/introspection/
service.rs

1use super::{Event, Function, LexicalId};
2use crate::error::{DeserializeError, SerializeError};
3use crate::ids::ServiceUuid;
4use crate::value_deserializer::{Deserialize, Deserializer};
5use crate::value_serializer::{Serialize, Serializer};
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7use std::collections::BTreeMap;
8use uuid::{uuid, Uuid};
9
10#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct Service {
12    schema: String,
13    name: String,
14    uuid: ServiceUuid,
15    version: u32,
16    functions: BTreeMap<u32, Function>,
17    events: BTreeMap<u32, Event>,
18    function_fallback: Option<String>,
19    event_fallback: Option<String>,
20}
21
22impl Service {
23    pub const NAMESPACE: Uuid = uuid!("de06b048-55f7-43b9-8d34-555795c2f4c6");
24
25    pub fn builder(
26        schema: impl Into<String>,
27        name: impl Into<String>,
28        uuid: ServiceUuid,
29        version: u32,
30    ) -> ServiceBuilder {
31        ServiceBuilder::new(schema, name, uuid, version)
32    }
33
34    pub fn lexical_id(&self) -> LexicalId {
35        LexicalId::service(&self.schema, &self.name)
36    }
37
38    pub fn schema(&self) -> &str {
39        &self.schema
40    }
41
42    pub fn name(&self) -> &str {
43        &self.name
44    }
45
46    pub fn uuid(&self) -> ServiceUuid {
47        self.uuid
48    }
49
50    pub fn version(&self) -> u32 {
51        self.version
52    }
53
54    pub fn functions(&self) -> &BTreeMap<u32, Function> {
55        &self.functions
56    }
57
58    pub fn events(&self) -> &BTreeMap<u32, Event> {
59        &self.events
60    }
61
62    pub fn function_fallback(&self) -> Option<&str> {
63        self.function_fallback.as_deref()
64    }
65
66    pub fn event_fallback(&self) -> Option<&str> {
67        self.event_fallback.as_deref()
68    }
69}
70
71#[derive(IntoPrimitive, TryFromPrimitive)]
72#[repr(u32)]
73enum ServiceField {
74    Schema = 0,
75    Name = 1,
76    Uuid = 2,
77    Version = 3,
78    Functions = 4,
79    Events = 5,
80    FunctionFallback = 6,
81    EventFallback = 7,
82}
83
84impl Serialize for Service {
85    fn serialize(&self, serializer: Serializer) -> Result<(), SerializeError> {
86        let num = 6
87            + (self.function_fallback.is_some() as usize)
88            + (self.event_fallback.is_some() as usize);
89        let mut serializer = serializer.serialize_struct(num)?;
90
91        serializer.serialize_field(ServiceField::Schema, &self.schema)?;
92        serializer.serialize_field(ServiceField::Name, &self.name)?;
93        serializer.serialize_field(ServiceField::Uuid, &self.uuid)?;
94        serializer.serialize_field(ServiceField::Version, &self.version)?;
95        serializer.serialize_field(ServiceField::Functions, &self.functions)?;
96        serializer.serialize_field(ServiceField::Events, &self.events)?;
97
98        if self.function_fallback.is_some() {
99            serializer.serialize_field(ServiceField::FunctionFallback, &self.function_fallback)?;
100        }
101
102        if self.event_fallback.is_some() {
103            serializer.serialize_field(ServiceField::EventFallback, &self.event_fallback)?;
104        }
105
106        serializer.finish()
107    }
108}
109
110impl Deserialize for Service {
111    fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
112        let mut deserializer = deserializer.deserialize_struct()?;
113
114        let mut schema = None;
115        let mut name = None;
116        let mut uuid = None;
117        let mut version = None;
118        let mut functions = None;
119        let mut events = None;
120        let mut function_fallback = None;
121        let mut event_fallback = None;
122
123        while deserializer.has_more_fields() {
124            let deserializer = deserializer.deserialize_field()?;
125
126            match deserializer.try_id()? {
127                ServiceField::Schema => schema = deserializer.deserialize().map(Some)?,
128                ServiceField::Name => name = deserializer.deserialize().map(Some)?,
129                ServiceField::Uuid => uuid = deserializer.deserialize().map(Some)?,
130                ServiceField::Version => version = deserializer.deserialize().map(Some)?,
131                ServiceField::Functions => functions = deserializer.deserialize().map(Some)?,
132                ServiceField::Events => events = deserializer.deserialize().map(Some)?,
133                ServiceField::FunctionFallback => function_fallback = deserializer.deserialize()?,
134                ServiceField::EventFallback => event_fallback = deserializer.deserialize()?,
135            }
136        }
137
138        deserializer.finish(Self {
139            schema: schema.ok_or(DeserializeError::InvalidSerialization)?,
140            name: name.ok_or(DeserializeError::InvalidSerialization)?,
141            uuid: uuid.ok_or(DeserializeError::InvalidSerialization)?,
142            version: version.ok_or(DeserializeError::InvalidSerialization)?,
143            functions: functions.ok_or(DeserializeError::InvalidSerialization)?,
144            events: events.ok_or(DeserializeError::InvalidSerialization)?,
145            function_fallback,
146            event_fallback,
147        })
148    }
149}
150
151#[derive(Debug, Clone)]
152pub struct ServiceBuilder {
153    schema: String,
154    name: String,
155    uuid: ServiceUuid,
156    version: u32,
157    functions: BTreeMap<u32, Function>,
158    events: BTreeMap<u32, Event>,
159    function_fallback: Option<String>,
160    event_fallback: Option<String>,
161}
162
163impl ServiceBuilder {
164    pub fn new(
165        schema: impl Into<String>,
166        name: impl Into<String>,
167        uuid: ServiceUuid,
168        version: u32,
169    ) -> Self {
170        Self {
171            schema: schema.into(),
172            name: name.into(),
173            uuid,
174            version,
175            functions: BTreeMap::new(),
176            events: BTreeMap::new(),
177            function_fallback: None,
178            event_fallback: None,
179        }
180    }
181
182    pub fn function(
183        mut self,
184        id: u32,
185        name: impl Into<String>,
186        args: Option<LexicalId>,
187        ok: Option<LexicalId>,
188        err: Option<LexicalId>,
189    ) -> Self {
190        self.functions
191            .insert(id, Function::new(id, name, args, ok, err));
192        self
193    }
194
195    pub fn event(
196        mut self,
197        id: u32,
198        name: impl Into<String>,
199        event_type: Option<LexicalId>,
200    ) -> Self {
201        self.events.insert(id, Event::new(id, name, event_type));
202        self
203    }
204
205    pub fn function_fallback(mut self, name: impl Into<String>) -> Self {
206        self.function_fallback = Some(name.into());
207        self
208    }
209
210    pub fn event_fallback(mut self, name: impl Into<String>) -> Self {
211        self.event_fallback = Some(name.into());
212        self
213    }
214
215    pub fn finish(self) -> Service {
216        Service {
217            schema: self.schema,
218            name: self.name,
219            uuid: self.uuid,
220            version: self.version,
221            functions: self.functions,
222            events: self.events,
223            function_fallback: self.function_fallback,
224            event_fallback: self.event_fallback,
225        }
226    }
227}