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        match annotation {
82            Annotation::Final => final_flag = true,
83            Annotation::Appendable => appendable = true,
84            Annotation::Mutable => mutable = true,
85            Annotation::Extensibility { kind } => {
86                if kind.eq_ignore_ascii_case("final") {
87                    final_flag = true;
88                } else if kind.eq_ignore_ascii_case("appendable") {
89                    appendable = true;
90                } else if kind.eq_ignore_ascii_case("mutable") {
91                    mutable = true;
92                }
93            }
94            Annotation::Builtin {
95                name,
96                params: Some(AnnotationParams::Raw(raw)),
97            } if name.eq_ignore_ascii_case("extensibility") => {
98                let value = raw.trim().trim_matches('"');
99                if value.eq_ignore_ascii_case("final") {
100                    final_flag = true;
101                } else if value.eq_ignore_ascii_case("appendable") {
102                    appendable = true;
103                } else if value.eq_ignore_ascii_case("mutable") {
104                    mutable = true;
105                }
106            }
107            _ => {}
108        }
109    }
110
111    if mutable {
112        Extensibility::Mutable
113    } else if appendable {
114        Extensibility::Appendable
115    } else if final_flag {
116        Extensibility::Final
117    } else {
118        Extensibility::None
119    }
120}
121
122#[cfg(test)]
123mod tests;