xidl_parser/hir/
serialization.rs1use super::{Annotation, AnnotationParams};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
5pub enum SerializeKind {
6 Cdr,
7 PlainCdr,
8 PlCdr,
9 PlainCdr2,
10 DelimitedCdr,
11 PlCdr2,
12}
13
14#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
15pub enum SerializeVersion {
16 Xcdr1,
17 Xcdr2,
18}
19
20#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy)]
21pub struct SerializeConfig {
22 pub explicit_kind: Option<SerializeKind>,
23 pub version: Option<SerializeVersion>,
24}
25
26#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
27pub enum Extensibility {
28 Final,
29 Appendable,
30 Mutable,
31 None,
32}
33
34impl SerializeConfig {
35 pub fn apply_pragma(&mut self, pragma: super::Pragma) {
36 match pragma {
37 super::Pragma::XidlcSerialize(kind) => self.explicit_kind = Some(kind),
38 super::Pragma::XidlcVersion(version) => {
39 self.version = Some(version);
40 self.explicit_kind = None;
41 }
42 super::Pragma::XidlcPackage(_)
43 | super::Pragma::XidlcOpenApiVersion(_)
44 | super::Pragma::XidlcOpenApiService { .. } => {}
45 }
46 }
47
48 pub fn resolve(&self, extensibility: Extensibility) -> SerializeKind {
49 if let Some(kind) = self.explicit_kind {
50 return kind;
51 }
52
53 match self.version {
54 None => SerializeKind::Cdr,
55 Some(SerializeVersion::Xcdr1) => match extensibility {
56 Extensibility::Mutable => SerializeKind::PlCdr,
57 Extensibility::Final | Extensibility::Appendable => SerializeKind::Cdr,
58 Extensibility::None => SerializeKind::PlainCdr,
59 },
60 Some(SerializeVersion::Xcdr2) => match extensibility {
61 Extensibility::Final => SerializeKind::PlainCdr2,
62 Extensibility::Appendable => SerializeKind::DelimitedCdr,
63 Extensibility::Mutable => SerializeKind::PlCdr2,
64 Extensibility::None => SerializeKind::Cdr,
65 },
66 }
67 }
68
69 pub fn resolve_for_annotations(&self, annotations: &[Annotation]) -> SerializeKind {
70 self.resolve(extensibility_from_annotations(annotations))
71 }
72}
73
74pub fn extensibility_from_annotations(annotations: &[Annotation]) -> Extensibility {
75 let mut final_flag = false;
76 let mut appendable = false;
77 let mut mutable = false;
78
79 for annotation in annotations {
80 if let Annotation::Builtin { name, .. } = annotation {
81 if name.eq_ignore_ascii_case("final") {
82 final_flag = true;
83 } else if name.eq_ignore_ascii_case("appendable") {
84 appendable = true;
85 } else if name.eq_ignore_ascii_case("mutable") {
86 mutable = true;
87 }
88 }
89
90 if let Annotation::Builtin { name, params } = annotation {
91 if name.eq_ignore_ascii_case("extensibility") {
92 if let Some(AnnotationParams::Raw(raw)) = params {
93 let value = raw.trim().trim_matches('"');
94 if value.eq_ignore_ascii_case("final") {
95 final_flag = true;
96 } else if value.eq_ignore_ascii_case("appendable") {
97 appendable = true;
98 } else if value.eq_ignore_ascii_case("mutable") {
99 mutable = true;
100 }
101 }
102 }
103 }
104 }
105
106 if mutable {
107 Extensibility::Mutable
108 } else if appendable {
109 Extensibility::Appendable
110 } else if final_flag {
111 Extensibility::Final
112 } else {
113 Extensibility::None
114 }
115}
116
117#[cfg(test)]
118mod tests;