1use serde::{Deserialize, Serialize};
2
3#[cfg(feature = "_python")]
4use pyo3::prelude::*;
5
6#[cfg(feature = "_access_functions")]
7use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
8
9use std::collections::HashMap;
10#[cfg(feature = "_access_functions")]
11use std::io::Write;
12
13pub type OrderedMap<T> = Vec<(String, T)>;
14
15#[derive(Serialize, Deserialize, Debug)]
16pub struct RawModel {
17 pub raw: serde_value::Value,
18 pub defines: HashMap<String, String>,
19}
20
21#[derive(Serialize, Deserialize, Debug)]
22pub struct SsdModel {
23 pub module: SsdModule,
24 pub defines: HashMap<String, String>,
25}
26
27#[cfg(feature = "_python")]
28macro_rules! Struct {
29 ($name: ident, $($prop_name: ident : $typ: ty),+) => {
30 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
31 #[pyclass]
32 pub struct $name {
33 $(#[pyo3(get)] pub $prop_name: $typ),+
34 }
35 };
36}
37
38#[cfg(not(feature = "_python"))]
39macro_rules! Struct {
40 ($name: ident, $($prop_name: ident : $typ: ty),+) => {
41 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
42 pub struct $name {
43 $(pub $prop_name: $typ),+
44 }
45 };
46}
47
48Struct!(SsdModule,
49 namespace: Namespace,
50 imports: Vec<Import>,
51 data_types: OrderedMap<DataType>,
52 enums: OrderedMap<Enum>,
53 services: OrderedMap<Service>
54);
55
56#[cfg(feature = "_python")]
57#[pymethods]
58impl SsdModule {
59 fn __repr__(&self) -> String {
60 format!("{self:?}")
61 }
62}
63
64impl SsdModule {
65 #[must_use]
66 pub fn new(
67 namespace: Namespace,
68 imports: Vec<Import>,
69 data_types: OrderedMap<DataType>,
70 enums: OrderedMap<Enum>,
71 services: OrderedMap<Service>,
72 ) -> Self {
73 Self {
74 namespace,
75 imports,
76 data_types,
77 enums,
78 services,
79 }
80 }
81}
82
83#[cfg(feature = "_access_functions")]
84impl SsdModule {
85 pub fn namespace(&mut self) -> Namespace {
86 self.namespace.clone()
87 }
88
89 pub fn imports(&mut self) -> Vec<Import> {
90 self.imports.clone()
91 }
92
93 pub fn data_types(&mut self) -> OrderedMap<DataType> {
94 self.data_types.clone()
95 }
96
97 pub fn enums(&mut self) -> OrderedMap<Enum> {
98 self.enums.clone()
99 }
100
101 pub fn services(&mut self) -> OrderedMap<Service> {
102 self.services.clone()
103 }
104}
105
106Struct!(Import,
107 path: Namespace,
108 attributes: Vec<Attribute>
109);
110
111#[cfg(feature = "_python")]
112#[pymethods]
113impl Import {
114 fn __repr__(&self) -> String {
115 format!("{self:?}")
116 }
117}
118
119impl Import {
120 #[must_use]
121 pub fn new(path: Namespace, attributes: Vec<Attribute>) -> Self {
122 Import { path, attributes }
123 }
124}
125
126#[cfg(feature = "_access_functions")]
127impl Import {
128 pub fn path(&mut self) -> Namespace {
129 self.path.clone()
130 }
131
132 pub fn attributes(&mut self) -> Vec<Attribute> {
133 self.attributes.clone()
134 }
135}
136
137Struct!(Dependency,
138 name: Namespace,
139 attributes: Vec<Attribute>,
140 comments: Vec<String>
141);
142
143#[cfg(feature = "_python")]
144#[pymethods]
145impl Dependency {
146 fn __repr__(&self) -> String {
147 format!("{self:?}")
148 }
149}
150
151impl Dependency {
152 #[must_use]
153 pub fn new(name: Namespace, attributes: Vec<Attribute>) -> Self {
154 Dependency {
155 name,
156 attributes,
157 comments: Vec::new(),
158 }
159 }
160
161 pub fn with_comments(mut self, comments: &mut Vec<String>) -> Self {
162 self.comments.append(comments);
163 self
164 }
165}
166
167#[cfg(feature = "_access_functions")]
168impl Dependency {
169 pub fn name(&mut self) -> Namespace {
170 self.name.clone()
171 }
172
173 pub fn attributes(&mut self) -> Vec<Attribute> {
174 self.attributes.clone()
175 }
176}
177
178Struct!(Parameter,
179 name: String,
180 value: Option<String>
181);
182
183#[cfg(feature = "_python")]
184#[pymethods]
185impl Parameter {
186 fn __repr__(&self) -> String {
187 format!("{self:?}")
188 }
189}
190
191#[cfg(feature = "_access_functions")]
192impl Parameter {
193 pub fn name(&mut self) -> String {
194 self.name.clone()
195 }
196
197 pub fn value(&mut self) -> Option<String> {
198 self.value.clone()
199 }
200}
201
202Struct!(Attribute,
203 name: Namespace,
204 parameters: Vec<Parameter>
205);
206
207#[cfg(feature = "_python")]
208#[pymethods]
209impl Attribute {
210 fn __repr__(&self) -> String {
211 format!("{self:?}")
212 }
213}
214
215impl Attribute {
216 #[must_use]
217 pub fn new(name: Namespace, parameters: Vec<(String, Option<String>)>) -> Self {
218 Self {
219 name,
220 parameters: parameters
221 .into_iter()
222 .map(|(name, value)| Parameter { name, value })
223 .collect(),
224 }
225 }
226}
227
228#[cfg(feature = "_access_functions")]
229impl Attribute {
230 pub fn name(&mut self) -> Namespace {
231 self.name.clone()
232 }
233
234 pub fn parameters(&mut self) -> Vec<Parameter> {
235 self.parameters.clone()
236 }
237}
238
239Struct!(DataType,
240 properties: OrderedMap<TypeName>,
241 attributes: Vec<Attribute>
242);
243
244#[cfg(feature = "_python")]
245#[pymethods]
246impl DataType {
247 fn __repr__(&self) -> String {
248 format!("{self:?}")
249 }
250}
251
252impl DataType {
253 #[must_use]
254 pub fn new(properties: OrderedMap<TypeName>, attributes: Vec<Attribute>) -> Self {
255 Self {
256 properties,
257 attributes,
258 }
259 }
260}
261
262#[cfg(feature = "_access_functions")]
263impl DataType {
264 pub fn properties(&mut self) -> OrderedMap<TypeName> {
265 self.properties.clone()
266 }
267
268 pub fn attributes(&mut self) -> Vec<Attribute> {
269 self.attributes.clone()
270 }
271}
272
273Struct!(Enum,
274 values: OrderedMap<EnumValue>,
275 attributes: Vec<Attribute>
276);
277
278#[cfg(feature = "_python")]
279#[pymethods]
280impl Enum {
281 fn __repr__(&self) -> String {
282 format!("{self:?}")
283 }
284}
285
286impl Enum {
287 #[must_use]
288 pub fn new(values: OrderedMap<EnumValue>, attributes: Vec<Attribute>) -> Self {
289 Self { values, attributes }
290 }
291}
292
293#[cfg(feature = "_access_functions")]
294impl Enum {
295 pub fn values(&mut self) -> OrderedMap<EnumValue> {
296 self.values.clone()
297 }
298
299 pub fn attributes(&mut self) -> Vec<Attribute> {
300 self.attributes.clone()
301 }
302}
303
304Struct!(Service,
305 dependencies: Vec<Dependency>,
306 functions: OrderedMap<Function>,
307 events: OrderedMap<Event>,
308 attributes: Vec<Attribute>
309);
310
311#[cfg(feature = "_python")]
312#[pymethods]
313impl Service {
314 fn __repr__(&self) -> String {
315 format!("{self:?}")
316 }
317}
318
319impl Service {
320 #[must_use]
321 pub fn new(
322 dependencies: Vec<Dependency>,
323 functions: OrderedMap<Function>,
324 events: OrderedMap<Event>,
325 attributes: Vec<Attribute>,
326 ) -> Self {
327 Self {
328 dependencies,
329 functions,
330 events,
331 attributes,
332 }
333 }
334}
335
336#[cfg(feature = "_access_functions")]
337impl Service {
338 pub fn dependencies(&mut self) -> Vec<Dependency> {
339 self.dependencies.clone()
340 }
341
342 pub fn functions(&mut self) -> OrderedMap<Function> {
343 self.functions.clone()
344 }
345
346 pub fn handlers(&mut self) -> OrderedMap<Function> {
347 const DEPRECATED: &str = "Using the property 'handlers' is deprecated and will be removed in future versions. Use 'functions' instead.";
348 let mut stderr = StandardStream::stderr(ColorChoice::Always);
349 if stderr
350 .set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))
351 .is_ok()
352 {
353 writeln!(&mut stderr, "{}", DEPRECATED).unwrap();
354
355 let _ = stderr.set_color(&ColorSpec::default());
356 } else {
357 eprintln!("{}", DEPRECATED);
358 }
359 self.functions()
360 }
361
362 pub fn events(&mut self) -> OrderedMap<Event> {
363 self.events.clone()
364 }
365
366 pub fn attributes(&mut self) -> Vec<Attribute> {
367 self.attributes.clone()
368 }
369}
370
371Struct!(Function,
372 arguments: OrderedMap<TypeName>,
373 return_type: Option<TypeName>,
374 attributes: Vec<Attribute>,
375 comments: Vec<String>
376);
377
378#[cfg(feature = "_python")]
379#[pymethods]
380impl Function {
381 fn __repr__(&self) -> String {
382 format!("{self:?}")
383 }
384}
385
386impl Function {
387 #[must_use]
388 pub fn new(
389 arguments: OrderedMap<TypeName>,
390 return_type: Option<TypeName>,
391 attributes: Vec<Attribute>,
392 ) -> Self {
393 Self {
394 arguments,
395 return_type,
396 attributes,
397 comments: Vec::new(),
398 }
399 }
400
401 pub fn with_comments(mut self, comments: &mut Vec<String>) -> Self {
402 self.comments.append(comments);
403 self
404 }
405}
406
407#[cfg(feature = "_access_functions")]
408impl Function {
409 pub fn arguments(&mut self) -> OrderedMap<TypeName> {
410 self.arguments.clone()
411 }
412
413 pub fn return_type(&mut self) -> Option<TypeName> {
414 self.return_type.clone()
415 }
416
417 pub fn attributes(&mut self) -> Vec<Attribute> {
418 self.attributes.clone()
419 }
420}
421
422Struct!(Event,
423 arguments: OrderedMap<TypeName>,
424 attributes: Vec<Attribute>,
425 comments: Vec<String>
426);
427
428#[cfg(feature = "_python")]
429#[pymethods]
430impl Event {
431 fn __repr__(&self) -> String {
432 format!("{self:?}")
433 }
434}
435
436impl Event {
437 #[must_use]
438 pub fn new(arguments: OrderedMap<TypeName>, attributes: Vec<Attribute>) -> Self {
439 Self {
440 arguments,
441 attributes,
442 comments: Vec::new(),
443 }
444 }
445
446 pub fn with_comments(mut self, comments: &mut Vec<String>) -> Self {
447 self.comments.append(comments);
448 self
449 }
450}
451
452#[cfg(feature = "_access_functions")]
453impl Event {
454 pub fn arguments(&mut self) -> OrderedMap<TypeName> {
455 self.arguments.clone()
456 }
457
458 pub fn attributes(&mut self) -> Vec<Attribute> {
459 self.attributes.clone()
460 }
461}
462
463Struct!(TypeName,
464 typ: Namespace,
465 is_list: bool,
466 count: Option<usize>,
467 attributes: Vec<Attribute>,
468 comments: Vec<String>
469);
470
471#[cfg(feature = "_python")]
472#[pymethods]
473impl TypeName {
474 fn __repr__(&self) -> String {
475 format!("{self:?}")
476 }
477}
478
479impl TypeName {
480 #[must_use]
481 pub fn new(
482 typ: Namespace,
483 is_list: bool,
484 count: Option<usize>,
485 attributes: Vec<Attribute>,
486 ) -> Self {
487 Self {
488 typ,
489 is_list,
490 count,
491 attributes,
492 comments: Vec::new(),
493 }
494 }
495
496 pub fn with_comments(mut self, comments: &mut Vec<String>) -> Self {
497 self.comments.append(comments);
498 self
499 }
500}
501
502#[cfg(feature = "_access_functions")]
503impl TypeName {
504 pub fn typ(&mut self) -> Namespace {
505 self.typ.clone()
506 }
507
508 pub fn is_list(&mut self) -> bool {
509 self.is_list
510 }
511
512 pub fn count(&mut self) -> Option<usize> {
513 self.count
514 }
515
516 pub fn attributes(&mut self) -> Vec<Attribute> {
517 self.attributes.clone()
518 }
519}
520
521Struct!(EnumValue,
522 value: Option<i64>,
523 attributes: Vec<Attribute>,
524 comments: Vec<String>
525);
526
527#[cfg(feature = "_python")]
528#[pymethods]
529impl EnumValue {
530 fn __repr__(&self) -> String {
531 format!("{self:?}")
532 }
533}
534
535impl EnumValue {
536 #[must_use]
537 pub fn new(value: Option<i64>, attributes: Vec<Attribute>) -> Self {
538 Self {
539 value,
540 attributes,
541 comments: Vec::new(),
542 }
543 }
544
545 pub fn with_comments(mut self, comments: &mut Vec<String>) -> Self {
546 self.comments.append(comments);
547 self
548 }
549}
550
551#[cfg(feature = "_access_functions")]
552impl EnumValue {
553 pub fn value(&mut self) -> Option<i64> {
554 self.value
555 }
556
557 pub fn attributes(&mut self) -> Vec<Attribute> {
558 self.attributes.clone()
559 }
560}
561
562Struct!(Namespace,
563 components: Vec<String>
564);
565
566impl IntoIterator for Namespace {
567 type Item = String;
568
569 type IntoIter = std::vec::IntoIter<Self::Item>;
570
571 fn into_iter(self) -> Self::IntoIter {
572 self.components.into_iter()
573 }
574}
575
576#[cfg(feature = "_python")]
577#[pymethods]
578impl Namespace {
579 fn __repr__(&self) -> String {
580 format!("{self:?}")
581 }
582}
583
584impl Namespace {
585 #[must_use]
586 pub fn new(v: &str) -> Self {
587 Namespace {
588 components: v.split("::").map(ToOwned::to_owned).collect(),
589 }
590 }
591
592 #[must_use]
593 pub fn from_vec(components: Vec<String>) -> Self {
594 Namespace { components }
595 }
596}
597
598#[cfg(feature = "_access_functions")]
599impl Namespace {
600 pub fn components(&mut self) -> Vec<String> {
601 self.components.clone()
602 }
603}
604
605impl ToString for Namespace {
606 fn to_string(&self) -> String {
607 self.components.join("::")
608 }
609}