Skip to main content

xidl_parser/hir/
serialization.rs

1use 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;