Skip to main content

xidl_parser/hir/
compound.rs

1use super::*;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Deserialize, Clone)]
5pub enum ConstrTypeDcl {
6    StructForwardDcl(StructForwardDcl),
7    StructDcl(StructDcl),
8    EnumDcl(EnumDcl),
9    UnionForwardDcl(UnionForwardDcl),
10    UnionDef(UnionDef),
11    BitsetDcl(BitsetDcl),
12    BitmaskDcl(BitmaskDcl),
13}
14
15impl ConstrTypeDcl {
16    /// Returns the name introduced by this constructed type declaration.
17    pub(crate) fn ident(&self) -> &str {
18        match self {
19            Self::StructDcl(value) => &value.ident,
20            Self::StructForwardDcl(value) => &value.ident,
21            Self::UnionDef(value) => &value.ident,
22            Self::UnionForwardDcl(value) => &value.ident,
23            Self::EnumDcl(value) => &value.ident,
24            Self::BitsetDcl(value) => &value.ident,
25            Self::BitmaskDcl(value) => &value.ident,
26        }
27    }
28}
29
30#[derive(Debug, Serialize, Deserialize, Clone)]
31pub struct UnionForwardDcl {
32    pub annotations: Vec<Annotation>,
33    pub ident: String,
34}
35
36#[derive(Debug, Serialize, Deserialize, Clone)]
37pub struct UnionDef {
38    pub annotations: Vec<Annotation>,
39    pub ident: String,
40    pub switch_type_spec: SwitchTypeSpec,
41    pub case: Vec<Case>,
42}
43
44#[derive(Debug, Serialize, Deserialize, Clone)]
45pub struct Case {
46    pub label: Vec<CaseLabel>,
47    pub element: ElementSpec,
48}
49
50#[derive(Debug, Serialize, Deserialize, Clone)]
51pub enum CaseLabel {
52    Value(ConstExpr),
53    Default,
54}
55
56#[derive(Debug, Serialize, Deserialize, Clone)]
57pub struct ElementSpec {
58    pub annotations: Vec<Annotation>,
59    pub ty: ElementSpecTy,
60    pub value: Declarator,
61    pub field_id: Option<u32>,
62    pub recursive: bool,
63}
64
65#[derive(Debug, Serialize, Deserialize, Clone)]
66pub enum ElementSpecTy {
67    TypeSpec(TypeSpec),
68    ConstrTypeDcl(ConstrTypeDcl),
69}
70
71#[derive(Debug, Serialize, Deserialize, Clone)]
72pub enum SwitchTypeSpec {
73    IntegerType(IntegerType),
74    CharType,
75    WideCharType,
76    BooleanType,
77    ScopedName(ScopedName),
78    OctetType,
79}
80
81#[derive(Debug, Serialize, Deserialize, Clone)]
82pub struct BitsetDcl {
83    pub annotations: Vec<Annotation>,
84    pub ident: String,
85    pub parent: Option<ScopedName>,
86    pub field: Vec<BitField>,
87}
88
89#[derive(Clone, Debug, Serialize, Deserialize)]
90pub enum BitFieldType {
91    Bool,
92    Octec,
93    SignedInt,
94    UnsignedInt,
95}
96
97#[derive(Debug, Serialize, Deserialize, Clone)]
98pub struct BitField {
99    pub ident: String,
100    pub pos: PositiveIntConst,
101    pub ty: Option<BitFieldType>,
102}
103
104#[derive(Debug, Serialize, Deserialize, Clone)]
105pub struct BitmaskDcl {
106    pub annotations: Vec<Annotation>,
107    pub ident: String,
108    pub value: Vec<BitValue>,
109}
110
111#[derive(Debug, Serialize, Deserialize, Clone)]
112pub struct BitValue {
113    pub position: usize,
114    pub annotations: Vec<Annotation>,
115    pub ident: String,
116}
117
118impl From<crate::typed_ast::ConstrTypeDcl> for ConstrTypeDcl {
119    fn from(value: crate::typed_ast::ConstrTypeDcl) -> Self {
120        match value {
121            crate::typed_ast::ConstrTypeDcl::StructDcl(value) => value.into(),
122            crate::typed_ast::ConstrTypeDcl::UnionDcl(value) => value.into(),
123            crate::typed_ast::ConstrTypeDcl::EnumDcl(value) => Self::EnumDcl(value.into()),
124            crate::typed_ast::ConstrTypeDcl::BitsetDcl(value) => Self::BitsetDcl(value.into()),
125            crate::typed_ast::ConstrTypeDcl::BitmaskDcl(value) => Self::BitmaskDcl(value.into()),
126        }
127    }
128}
129
130impl From<crate::typed_ast::StructDcl> for ConstrTypeDcl {
131    fn from(value: crate::typed_ast::StructDcl) -> Self {
132        match value {
133            crate::typed_ast::StructDcl::StructForwardDcl(value) => {
134                Self::StructForwardDcl(value.into())
135            }
136            crate::typed_ast::StructDcl::StructDef(value) => Self::StructDcl(value.into()),
137        }
138    }
139}
140
141impl From<crate::typed_ast::UnionDcl> for ConstrTypeDcl {
142    fn from(value: crate::typed_ast::UnionDcl) -> Self {
143        match value {
144            crate::typed_ast::UnionDcl::UnionForwardDcl(value) => {
145                Self::UnionForwardDcl(value.into())
146            }
147            crate::typed_ast::UnionDcl::UnionDef(value) => Self::UnionDef(value.into()),
148        }
149    }
150}
151
152impl From<crate::typed_ast::UnionForwardDcl> for UnionForwardDcl {
153    fn from(value: crate::typed_ast::UnionForwardDcl) -> Self {
154        Self {
155            annotations: vec![],
156            ident: value.0.0,
157        }
158    }
159}
160
161impl From<crate::typed_ast::UnionDef> for UnionDef {
162    fn from(value: crate::typed_ast::UnionDef) -> Self {
163        let mut cases = value
164            .case
165            .into_iter()
166            .map(Case::from)
167            .collect::<Vec<Case>>();
168        let mut member_ids = std::collections::HashMap::new();
169        let mut next_field_id = 1u32;
170
171        for case in &mut cases {
172            let name = declarator_name(&case.element.value).to_string();
173            if let Some(id) = case.element.field_id {
174                let entry = member_ids.entry(name.clone()).or_insert(id);
175                case.element.field_id = Some(*entry);
176            } else if let Some(existing) = member_ids.get(&name) {
177                case.element.field_id = Some(*existing);
178            } else {
179                member_ids.insert(name, next_field_id);
180                case.element.field_id = Some(next_field_id);
181                next_field_id += 1;
182            }
183        }
184
185        Self {
186            annotations: vec![],
187            ident: value.ident.0,
188            switch_type_spec: value.switch_type_spec.into(),
189            case: cases,
190        }
191    }
192}
193
194impl From<crate::typed_ast::Case> for Case {
195    fn from(value: crate::typed_ast::Case) -> Self {
196        Self {
197            label: value.label.into_iter().map(Into::into).collect(),
198            element: value.element.into(),
199        }
200    }
201}
202
203impl From<crate::typed_ast::CaseLabel> for CaseLabel {
204    fn from(value: crate::typed_ast::CaseLabel) -> Self {
205        match value {
206            crate::typed_ast::CaseLabel::Case(value) => Self::Value(value.into()),
207            crate::typed_ast::CaseLabel::Default => Self::Default,
208        }
209    }
210}
211
212impl From<crate::typed_ast::ElementSpec> for ElementSpec {
213    fn from(value: crate::typed_ast::ElementSpec) -> Self {
214        let annotations = expand_annotations(value.annotations);
215        Self {
216            field_id: annotation_id_value(&annotations),
217            annotations,
218            ty: value.ty.into(),
219            value: value.value.into(),
220            recursive: false,
221        }
222    }
223}
224
225impl From<crate::typed_ast::ElementSpecTy> for ElementSpecTy {
226    fn from(value: crate::typed_ast::ElementSpecTy) -> Self {
227        match value {
228            crate::typed_ast::ElementSpecTy::TypeSpec(value) => Self::TypeSpec(value.into()),
229            crate::typed_ast::ElementSpecTy::ConstrTypeDcl(value) => {
230                Self::ConstrTypeDcl(value.into())
231            }
232        }
233    }
234}
235
236impl From<crate::typed_ast::SwitchTypeSpec> for SwitchTypeSpec {
237    fn from(value: crate::typed_ast::SwitchTypeSpec) -> Self {
238        match value {
239            crate::typed_ast::SwitchTypeSpec::IntegerType(value) => Self::IntegerType(value.into()),
240            crate::typed_ast::SwitchTypeSpec::CharType(_) => Self::CharType,
241            crate::typed_ast::SwitchTypeSpec::WideCharType(_) => Self::WideCharType,
242            crate::typed_ast::SwitchTypeSpec::BooleanType(_) => Self::BooleanType,
243            crate::typed_ast::SwitchTypeSpec::ScopedName(value) => Self::ScopedName(value.into()),
244            crate::typed_ast::SwitchTypeSpec::OctetType(_) => Self::OctetType,
245        }
246    }
247}
248
249impl From<crate::typed_ast::BitsetDcl> for BitsetDcl {
250    fn from(value: crate::typed_ast::BitsetDcl) -> Self {
251        let mut field = Vec::new();
252        for bitfield in value.field {
253            let pos = bitfield.spec.pos;
254            let ty = bitfield.spec.dst_ty.map(Into::into);
255            for ident in bitfield.ident {
256                field.push(BitField {
257                    ident: ident.0,
258                    pos: pos.clone().into(),
259                    ty: ty.clone(),
260                });
261            }
262        }
263
264        Self {
265            annotations: vec![],
266            ident: value.ident.0,
267            parent: value.parent.map(Into::into),
268            field,
269        }
270    }
271}
272
273impl From<crate::typed_ast::DestinationType> for BitFieldType {
274    fn from(value: crate::typed_ast::DestinationType) -> Self {
275        match value {
276            crate::typed_ast::DestinationType::BooleanType(_) => Self::Bool,
277            crate::typed_ast::DestinationType::OctetType(_) => Self::Octec,
278            crate::typed_ast::DestinationType::IntegerType(value) => {
279                if matches!(value, crate::typed_ast::IntegerType::SignedInt(_)) {
280                    Self::SignedInt
281                } else {
282                    Self::UnsignedInt
283                }
284            }
285        }
286    }
287}
288
289impl From<crate::typed_ast::BitmaskDcl> for BitmaskDcl {
290    fn from(value: crate::typed_ast::BitmaskDcl) -> Self {
291        let mut bits = vec![];
292        for (idx, bitvalue) in value.value.into_iter().enumerate() {
293            let mut position = idx;
294            for annotation in &bitvalue.annotations {
295                let crate::typed_ast::AnnotationName::Builtin(name) = &annotation.name else {
296                    continue;
297                };
298                if !name.eq_ignore_ascii_case("position") {
299                    continue;
300                }
301
302                let Some(crate::typed_ast::AnnotationParams::Raw(v)) = &annotation.params else {
303                    continue;
304                };
305
306                if let Ok(v) = v.parse::<usize>() {
307                    position = v;
308                }
309            }
310            let mut bit: BitValue = bitvalue.into();
311            bit.position = position;
312            bits.push(bit);
313        }
314        Self {
315            annotations: vec![],
316            ident: value.ident.0,
317            value: bits,
318        }
319    }
320}
321
322impl From<crate::typed_ast::BitValue> for BitValue {
323    fn from(value: crate::typed_ast::BitValue) -> Self {
324        Self {
325            position: 0,
326            annotations: expand_annotations(value.annotations),
327            ident: value.ident.0,
328        }
329    }
330}
331
332fn declarator_name(value: &Declarator) -> &str {
333    match value {
334        Declarator::SimpleDeclarator(value) => &value.0,
335        Declarator::ArrayDeclarator(value) => &value.ident,
336    }
337}