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::Custom(_) => {}
38            super::Pragma::XidlcSerialize(kind) => self.explicit_kind = Some(kind),
39            super::Pragma::XidlcVersion(version) => {
40                self.version = Some(version);
41                self.explicit_kind = None;
42            }
43            super::Pragma::XidlcPackage(_)
44            | super::Pragma::XidlcOpenApiVersion(_)
45            | super::Pragma::XidlcOpenApiService { .. } => {}
46        }
47    }
48
49    pub fn resolve(&self, extensibility: Extensibility) -> SerializeKind {
50        if let Some(kind) = self.explicit_kind {
51            return kind;
52        }
53
54        match self.version {
55            None => SerializeKind::Cdr,
56            Some(SerializeVersion::Xcdr1) => match extensibility {
57                Extensibility::Mutable => SerializeKind::PlCdr,
58                Extensibility::Final | Extensibility::Appendable => SerializeKind::Cdr,
59                Extensibility::None => SerializeKind::PlainCdr,
60            },
61            Some(SerializeVersion::Xcdr2) => match extensibility {
62                Extensibility::Final => SerializeKind::PlainCdr2,
63                Extensibility::Appendable => SerializeKind::DelimitedCdr,
64                Extensibility::Mutable => SerializeKind::PlCdr2,
65                Extensibility::None => SerializeKind::Cdr,
66            },
67        }
68    }
69
70    pub fn resolve_for_annotations(&self, annotations: &[Annotation]) -> SerializeKind {
71        self.resolve(extensibility_from_annotations(annotations))
72    }
73}
74
75pub fn extensibility_from_annotations(annotations: &[Annotation]) -> Extensibility {
76    let mut final_flag = false;
77    let mut appendable = false;
78    let mut mutable = false;
79
80    for annotation in annotations {
81        if let Annotation::Builtin { name, .. } = annotation {
82            if name.eq_ignore_ascii_case("final") {
83                final_flag = true;
84            } else if name.eq_ignore_ascii_case("appendable") {
85                appendable = true;
86            } else if name.eq_ignore_ascii_case("mutable") {
87                mutable = true;
88            }
89        }
90
91        if let Annotation::Builtin { name, params } = annotation {
92            if name.eq_ignore_ascii_case("extensibility") {
93                if let Some(AnnotationParams::Raw(raw)) = params {
94                    let value = raw.trim().trim_matches('"');
95                    if value.eq_ignore_ascii_case("final") {
96                        final_flag = true;
97                    } else if value.eq_ignore_ascii_case("appendable") {
98                        appendable = true;
99                    } else if value.eq_ignore_ascii_case("mutable") {
100                        mutable = true;
101                    }
102                }
103            }
104        }
105    }
106
107    if mutable {
108        Extensibility::Mutable
109    } else if appendable {
110        Extensibility::Appendable
111    } else if final_flag {
112        Extensibility::Final
113    } else {
114        Extensibility::None
115    }
116}
117
118#[cfg(test)]
119mod tests;