Skip to main content

xidl_parser/hir/
mod.rs

1mod enum_dcl;
2pub use enum_dcl::*;
3
4mod struct_dcl;
5pub use struct_dcl::*;
6
7mod annotation;
8pub use annotation::*;
9
10mod expr;
11pub use expr::*;
12
13mod declarator;
14pub use declarator::*;
15
16mod types;
17pub use types::*;
18
19mod const_dcl;
20pub use const_dcl::*;
21
22mod interface;
23pub use interface::*;
24
25mod type_dcl;
26pub use type_dcl::*;
27
28mod exception_dcl;
29pub use exception_dcl::*;
30
31mod interface_codegen;
32
33use serde::{Deserialize, Serialize};
34use serde_json::Value;
35use std::collections::HashMap;
36
37#[derive(Debug, Serialize, Deserialize, Clone)]
38pub struct Specification(pub Vec<Definition>);
39
40pub type ParserProperties = HashMap<String, Value>;
41
42#[derive(Debug, Serialize, Deserialize, Clone)]
43pub enum Definition {
44    ModuleDcl(ModuleDcl),
45    Pragma(Pragma),
46    ConstrTypeDcl(ConstrTypeDcl),
47    TypeDcl(TypeDcl),
48    ConstDcl(ConstDcl),
49    ExceptDcl(ExceptDcl),
50    InterfaceDcl(InterfaceDcl),
51}
52
53#[derive(Debug, Serialize, Deserialize, Clone)]
54pub struct ModuleDcl {
55    pub annotations: Vec<Annotation>,
56    pub ident: String,
57    pub definition: Vec<Definition>,
58}
59
60#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
61pub enum SerializeKind {
62    Cdr,
63    PlainCdr,
64    PlCdr,
65    PlainCdr2,
66    DelimitedCdr,
67    PlCdr2,
68}
69
70#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
71pub enum SerializeVersion {
72    Xcdr1,
73    Xcdr2,
74}
75
76#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy)]
77pub struct SerializeConfig {
78    pub explicit_kind: Option<SerializeKind>,
79    pub version: Option<SerializeVersion>,
80}
81
82#[derive(Debug, Serialize, Deserialize, Clone)]
83pub enum Pragma {
84    XidlcSerialize(SerializeKind),
85    XidlcVersion(SerializeVersion),
86    XidlcPackage(String),
87    XidlcOpenApiVersion(String),
88    XidlcOpenApiService {
89        base_url: String,
90        description: Option<String>,
91    },
92}
93
94#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
95pub enum Extensibility {
96    Final,
97    Appendable,
98    Mutable,
99    None,
100}
101
102impl SerializeConfig {
103    pub fn apply_pragma(&mut self, pragma: Pragma) {
104        match pragma {
105            Pragma::XidlcSerialize(kind) => {
106                self.explicit_kind = Some(kind);
107            }
108            Pragma::XidlcVersion(version) => {
109                self.version = Some(version);
110                self.explicit_kind = None;
111            }
112            Pragma::XidlcPackage(_)
113            | Pragma::XidlcOpenApiVersion(_)
114            | Pragma::XidlcOpenApiService { .. } => {}
115        }
116    }
117
118    pub fn resolve(&self, extensibility: Extensibility) -> SerializeKind {
119        if let Some(kind) = self.explicit_kind {
120            return kind;
121        }
122
123        match self.version {
124            None => SerializeKind::Cdr,
125            Some(SerializeVersion::Xcdr1) => match extensibility {
126                Extensibility::Mutable => SerializeKind::PlCdr,
127                Extensibility::Final | Extensibility::Appendable => SerializeKind::Cdr,
128                Extensibility::None => SerializeKind::PlainCdr,
129            },
130            Some(SerializeVersion::Xcdr2) => match extensibility {
131                Extensibility::Final => SerializeKind::PlainCdr2,
132                Extensibility::Appendable => SerializeKind::DelimitedCdr,
133                Extensibility::Mutable => SerializeKind::PlCdr2,
134                Extensibility::None => SerializeKind::Cdr,
135            },
136        }
137    }
138
139    pub fn resolve_for_annotations(&self, annotations: &[Annotation]) -> SerializeKind {
140        self.resolve(extensibility_from_annotations(annotations))
141    }
142}
143
144pub fn extensibility_from_annotations(annotations: &[Annotation]) -> Extensibility {
145    let mut final_flag = false;
146    let mut appendable = false;
147    let mut mutable = false;
148    for anno in annotations {
149        if let Annotation::Builtin { name, .. } = anno {
150            if name.eq_ignore_ascii_case("final") {
151                final_flag = true;
152            } else if name.eq_ignore_ascii_case("appendable") {
153                appendable = true;
154            } else if name.eq_ignore_ascii_case("mutable") {
155                mutable = true;
156            }
157        }
158        if let Annotation::Builtin { name, params } = anno {
159            if name.eq_ignore_ascii_case("extensibility") {
160                if let Some(AnnotationParams::Raw(raw)) = params {
161                    let value = raw.trim().trim_matches('"');
162                    if value.eq_ignore_ascii_case("final") {
163                        final_flag = true;
164                    } else if value.eq_ignore_ascii_case("appendable") {
165                        appendable = true;
166                    } else if value.eq_ignore_ascii_case("mutable") {
167                        mutable = true;
168                    }
169                }
170            }
171        }
172    }
173
174    if mutable {
175        Extensibility::Mutable
176    } else if appendable {
177        Extensibility::Appendable
178    } else if final_flag {
179        Extensibility::Final
180    } else {
181        Extensibility::None
182    }
183}
184
185#[derive(Debug, Serialize, Deserialize, Clone)]
186pub enum ConstrTypeDcl {
187    StructForwardDcl(StructForwardDcl),
188    StructDcl(StructDcl),
189    EnumDcl(EnumDcl),
190    UnionForwardDcl(UnionForwardDcl),
191    UnionDef(UnionDef),
192    BitsetDcl(BitsetDcl),
193    BitmaskDcl(BitmaskDcl),
194}
195
196#[derive(Debug, Serialize, Deserialize, Clone)]
197pub struct UnionForwardDcl {
198    pub annotations: Vec<Annotation>,
199    pub ident: String,
200}
201
202#[derive(Debug, Serialize, Deserialize, Clone)]
203pub struct UnionDef {
204    pub annotations: Vec<Annotation>,
205    pub ident: String,
206    pub switch_type_spec: SwitchTypeSpec,
207    pub case: Vec<Case>,
208}
209
210impl UnionDef {
211    pub fn serialize_kind(&self, config: &SerializeConfig) -> SerializeKind {
212        config.resolve_for_annotations(&self.annotations)
213    }
214}
215
216#[derive(Debug, Serialize, Deserialize, Clone)]
217pub struct Case {
218    pub label: Vec<CaseLabel>,
219    pub element: ElementSpec,
220}
221
222#[derive(Debug, Serialize, Deserialize, Clone)]
223pub enum CaseLabel {
224    Value(ConstExpr),
225    Default,
226}
227
228#[derive(Debug, Serialize, Deserialize, Clone)]
229pub struct ElementSpec {
230    pub annotations: Vec<Annotation>,
231    pub ty: ElementSpecTy,
232    pub value: Declarator,
233    pub field_id: Option<u32>,
234}
235
236#[derive(Debug, Serialize, Deserialize, Clone)]
237pub enum ElementSpecTy {
238    TypeSpec(TypeSpec),
239    ConstrTypeDcl(ConstrTypeDcl),
240}
241
242#[derive(Debug, Serialize, Deserialize, Clone)]
243pub enum SwitchTypeSpec {
244    IntegerType(IntegerType),
245    CharType,
246    WideCharType,
247    BooleanType,
248    ScopedName(ScopedName),
249    OctetType,
250}
251
252#[derive(Debug, Serialize, Deserialize, Clone)]
253pub struct BitsetDcl {
254    pub annotations: Vec<Annotation>,
255    pub ident: String,
256    pub parent: Option<ScopedName>,
257    pub field: Vec<BitField>,
258}
259
260impl BitsetDcl {
261    pub fn serialize_kind(&self, config: &SerializeConfig) -> SerializeKind {
262        config.resolve_for_annotations(&self.annotations)
263    }
264}
265
266#[derive(Clone, Debug, Serialize, Deserialize)]
267pub enum BitFieldType {
268    Bool,
269    Octec,
270    SignedInt,
271    UnsignedInt,
272}
273
274#[derive(Debug, Serialize, Deserialize, Clone)]
275pub struct BitField {
276    pub ident: String,
277    pub pos: PositiveIntConst,
278    pub ty: Option<BitFieldType>,
279}
280
281#[derive(Debug, Serialize, Deserialize, Clone)]
282pub struct BitmaskDcl {
283    pub annotations: Vec<Annotation>,
284    pub ident: String,
285    pub value: Vec<BitValue>,
286}
287
288impl BitmaskDcl {
289    pub fn serialize_kind(&self, config: &SerializeConfig) -> SerializeKind {
290        config.resolve_for_annotations(&self.annotations)
291    }
292}
293
294#[derive(Debug, Serialize, Deserialize, Clone)]
295pub struct BitValue {
296    pub annotations: Vec<Annotation>,
297    pub ident: String,
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct ScopedName {
302    pub name: Vec<String>,
303    pub is_root: bool,
304}
305
306impl From<crate::typed_ast::ScopedName> for ScopedName {
307    fn from(typed_ast: crate::typed_ast::ScopedName) -> Self {
308        let is_root = typed_ast.node_text.starts_with("::");
309        let mut v = vec![];
310        get_scoped_name(&mut v, &typed_ast);
311        let name = v.into_iter().map(ToOwned::to_owned).collect();
312
313        Self { name, is_root }
314    }
315}
316
317fn get_scoped_name<'a>(pre: &mut Vec<&'a str>, value: &'a crate::typed_ast::ScopedName) {
318    if let Some(value) = &value.scoped_name {
319        get_scoped_name(pre, value);
320    }
321
322    pre.push(&value.identifier.0);
323}
324
325impl From<crate::typed_ast::Specification> for Specification {
326    fn from(value: crate::typed_ast::Specification) -> Self {
327        spec_from_typed_ast(value, true)
328    }
329}
330
331impl Specification {
332    pub fn from_typed_ast_with_properties(
333        value: crate::typed_ast::Specification,
334        properties: ParserProperties,
335    ) -> Self {
336        let expand_interface = properties
337            .get("expand_interface")
338            .and_then(Value::as_bool)
339            .unwrap_or(true);
340        spec_from_typed_ast(value, expand_interface)
341    }
342}
343
344pub(crate) fn spec_from_typed_ast(
345    value: crate::typed_ast::Specification,
346    expand_interfaces: bool,
347) -> Specification {
348    let mut defs = Vec::new();
349    let mut modules = Vec::new();
350    collect_defs(value.0, &mut modules, expand_interfaces, &mut defs);
351    Specification(defs)
352}
353
354fn collect_defs(
355    defs: Vec<crate::typed_ast::Definition>,
356    modules: &mut Vec<String>,
357    expand_interfaces: bool,
358    out: &mut Vec<Definition>,
359) {
360    for def in defs {
361        match def {
362            crate::typed_ast::Definition::ModuleDcl(module) => {
363                let ident = module.ident.0;
364                let annotations = expand_annotations(module.annotations);
365                modules.push(ident.clone());
366                let mut inner = Vec::new();
367                collect_defs(module.definition, modules, expand_interfaces, &mut inner);
368                modules.pop();
369                out.push(Definition::ModuleDcl(ModuleDcl {
370                    annotations,
371                    ident,
372                    definition: inner,
373                }));
374            }
375            crate::typed_ast::Definition::PreprocCall(call) => {
376                if let Some(pragma) = parse_xidlc_pragma(&call) {
377                    out.push(Definition::Pragma(pragma));
378                }
379            }
380            crate::typed_ast::Definition::TypeDcl(type_dcl) => {
381                let type_dcl: TypeDcl = type_dcl.into();
382                out.push(Definition::TypeDcl(type_dcl));
383            }
384            crate::typed_ast::Definition::ConstDcl(const_dcl) => {
385                out.push(Definition::ConstDcl(const_dcl.into()));
386            }
387            crate::typed_ast::Definition::ExceptDcl(except_dcl) => {
388                out.push(Definition::ExceptDcl(except_dcl.into()));
389            }
390            crate::typed_ast::Definition::InterfaceDcl(interface_dcl) => {
391                let interface: InterfaceDcl = interface_dcl.into();
392                if expand_interfaces {
393                    let extra = interface_codegen::expand_interface(&interface, modules)
394                        .unwrap_or_else(|err| {
395                            panic!("interface expansion failed: {err}");
396                        });
397                    out.extend(extra);
398                }
399                out.push(Definition::InterfaceDcl(interface));
400            }
401            crate::typed_ast::Definition::TemplateModuleDcl(_)
402            | crate::typed_ast::Definition::TemplateModuleInst(_)
403            | crate::typed_ast::Definition::PreprocInclude(_)
404            | crate::typed_ast::Definition::PreprocDefine(_) => {}
405        }
406    }
407}
408
409fn parse_xidlc_pragma(call: &crate::typed_ast::PreprocCall) -> Option<Pragma> {
410    let directive = call.directive.0.as_str();
411    if !directive.eq_ignore_ascii_case("#pragma") && !directive.eq_ignore_ascii_case("#progma") {
412        return None;
413    }
414    let arg = call.argument.as_ref()?.0.as_str();
415    let mut parts = arg.split_whitespace();
416    let namespace = parts.next()?;
417    if !namespace.eq_ignore_ascii_case("xidlc") {
418        return None;
419    }
420    let token = parts.next()?;
421    let rest = parts.collect::<Vec<_>>().join(" ");
422
423    if token.eq_ignore_ascii_case("XCDR1") {
424        return Some(Pragma::XidlcVersion(SerializeVersion::Xcdr1));
425    }
426    if token.eq_ignore_ascii_case("XCDR2") {
427        return Some(Pragma::XidlcVersion(SerializeVersion::Xcdr2));
428    }
429    if token.eq_ignore_ascii_case("package") {
430        if !rest.is_empty() {
431            return Some(Pragma::XidlcPackage(trim_pragma_value(&rest)));
432        }
433        return None;
434    }
435    if token.eq_ignore_ascii_case("version") {
436        if !rest.is_empty() {
437            return Some(Pragma::XidlcOpenApiVersion(trim_pragma_value(&rest)));
438        }
439        return None;
440    }
441    if token.eq_ignore_ascii_case("service") {
442        if let Some((base_url, description)) = parse_pragma_service(&rest) {
443            return Some(Pragma::XidlcOpenApiService {
444                base_url,
445                description,
446            });
447        }
448        return None;
449    }
450
451    if let Some(inner) = token
452        .strip_prefix("serialize(")
453        .and_then(|value| value.strip_suffix(')'))
454    {
455        let inner = inner.trim();
456        if inner.eq_ignore_ascii_case("XCDR1") {
457            return Some(Pragma::XidlcVersion(SerializeVersion::Xcdr1));
458        }
459        if inner.eq_ignore_ascii_case("XCDR2") {
460            return Some(Pragma::XidlcVersion(SerializeVersion::Xcdr2));
461        }
462        if let Some(kind) = parse_serialize_kind(inner) {
463            return Some(Pragma::XidlcSerialize(kind));
464        }
465    }
466
467    None
468}
469
470fn trim_pragma_value(value: &str) -> String {
471    let value = value.trim();
472    if value.len() >= 2 {
473        let first = value.chars().next().unwrap();
474        let last = value.chars().last().unwrap();
475        if (first == '"' && last == '"') || (first == '\'' && last == '\'') {
476            return value[1..value.len() - 1].to_string();
477        }
478    }
479    value.to_string()
480}
481
482fn parse_pragma_service(value: &str) -> Option<(String, Option<String>)> {
483    let value = value.trim();
484    if value.is_empty() {
485        return None;
486    }
487
488    let mut base_url = None;
489    let mut remainder = "";
490
491    if value.starts_with('"') || value.starts_with('\'') {
492        let quote = value.chars().next().unwrap();
493        let mut end = None;
494        for (index, ch) in value.char_indices().skip(1) {
495            if ch == quote {
496                end = Some(index);
497                break;
498            }
499        }
500        if let Some(end) = end {
501            base_url = Some(value[1..end].to_string());
502            remainder = value[end + 1..].trim();
503        }
504    }
505
506    if base_url.is_none() {
507        let mut parts = value.splitn(2, char::is_whitespace);
508        base_url = parts.next().map(str::to_string);
509        remainder = parts.next().unwrap_or("").trim();
510    }
511
512    let base_url = base_url?;
513    let description = if remainder.is_empty() {
514        None
515    } else {
516        Some(trim_pragma_value(remainder))
517    };
518
519    Some((base_url, description))
520}
521
522fn parse_serialize_kind(value: &str) -> Option<SerializeKind> {
523    let value = value.trim();
524    if value.eq_ignore_ascii_case("CDR") {
525        Some(SerializeKind::Cdr)
526    } else if value.eq_ignore_ascii_case("PLAIN_CDR") {
527        Some(SerializeKind::PlainCdr)
528    } else if value.eq_ignore_ascii_case("PL_CDR") {
529        Some(SerializeKind::PlCdr)
530    } else if value.eq_ignore_ascii_case("PLAIN_CDR2") {
531        Some(SerializeKind::PlainCdr2)
532    } else if value.eq_ignore_ascii_case("DELIMITED_CDR") {
533        Some(SerializeKind::DelimitedCdr)
534    } else if value.eq_ignore_ascii_case("PL_CDR2") {
535        Some(SerializeKind::PlCdr2)
536    } else {
537        None
538    }
539}
540
541impl From<crate::typed_ast::ConstrTypeDcl> for ConstrTypeDcl {
542    fn from(value: crate::typed_ast::ConstrTypeDcl) -> Self {
543        match value {
544            crate::typed_ast::ConstrTypeDcl::StructDcl(struct_dcl) => struct_dcl.into(),
545            crate::typed_ast::ConstrTypeDcl::UnionDcl(union_dcl) => union_dcl.into(),
546            crate::typed_ast::ConstrTypeDcl::EnumDcl(enum_dcl) => Self::EnumDcl(enum_dcl.into()),
547            crate::typed_ast::ConstrTypeDcl::BitsetDcl(bitset_dcl) => {
548                Self::BitsetDcl(bitset_dcl.into())
549            }
550            crate::typed_ast::ConstrTypeDcl::BitmaskDcl(bitmask_dcl) => {
551                Self::BitmaskDcl(bitmask_dcl.into())
552            }
553        }
554    }
555}
556
557impl From<crate::typed_ast::StructDcl> for ConstrTypeDcl {
558    fn from(value: crate::typed_ast::StructDcl) -> Self {
559        match value {
560            crate::typed_ast::StructDcl::StructForwardDcl(forward) => {
561                Self::StructForwardDcl(forward.into())
562            }
563            crate::typed_ast::StructDcl::StructDef(def) => Self::StructDcl(def.into()),
564        }
565    }
566}
567
568impl From<crate::typed_ast::UnionDcl> for ConstrTypeDcl {
569    fn from(value: crate::typed_ast::UnionDcl) -> Self {
570        match value {
571            crate::typed_ast::UnionDcl::UnionForwardDcl(forward) => {
572                Self::UnionForwardDcl(forward.into())
573            }
574            crate::typed_ast::UnionDcl::UnionDef(def) => Self::UnionDef(def.into()),
575        }
576    }
577}
578
579impl From<crate::typed_ast::UnionForwardDcl> for UnionForwardDcl {
580    fn from(value: crate::typed_ast::UnionForwardDcl) -> Self {
581        Self {
582            annotations: vec![],
583            ident: value.0.0,
584        }
585    }
586}
587
588impl From<crate::typed_ast::UnionDef> for UnionDef {
589    fn from(value: crate::typed_ast::UnionDef) -> Self {
590        let mut cases = value
591            .case
592            .into_iter()
593            .map(Into::into)
594            .collect::<Vec<Case>>();
595        let mut member_ids = std::collections::HashMap::new();
596        let mut next_field_id = 1u32;
597        for case in cases.iter_mut() {
598            let name = declarator_name(&case.element.value).to_string();
599            if let Some(id) = case.element.field_id {
600                let entry = member_ids.entry(name.clone()).or_insert(id);
601                case.element.field_id = Some(*entry);
602                continue;
603            }
604            if let Some(existing) = member_ids.get(&name) {
605                case.element.field_id = Some(*existing);
606                continue;
607            }
608            member_ids.insert(name, next_field_id);
609            case.element.field_id = Some(next_field_id);
610            next_field_id += 1;
611        }
612        Self {
613            annotations: vec![],
614            ident: value.ident.0,
615            switch_type_spec: value.switch_type_spec.into(),
616            case: cases,
617        }
618    }
619}
620
621impl From<crate::typed_ast::Case> for Case {
622    fn from(value: crate::typed_ast::Case) -> Self {
623        Self {
624            label: value.label.into_iter().map(Into::into).collect(),
625            element: value.element.into(),
626        }
627    }
628}
629
630impl From<crate::typed_ast::CaseLabel> for CaseLabel {
631    fn from(value: crate::typed_ast::CaseLabel) -> Self {
632        match value {
633            crate::typed_ast::CaseLabel::Case(expr) => Self::Value(expr.into()),
634            crate::typed_ast::CaseLabel::Default => Self::Default,
635        }
636    }
637}
638
639impl From<crate::typed_ast::ElementSpec> for ElementSpec {
640    fn from(value: crate::typed_ast::ElementSpec) -> Self {
641        let annotations = expand_annotations(value.annotations);
642        let field_id = annotation_id_value(&annotations);
643        Self {
644            annotations,
645            ty: value.ty.into(),
646            value: value.value.into(),
647            field_id,
648        }
649    }
650}
651
652impl From<crate::typed_ast::ElementSpecTy> for ElementSpecTy {
653    fn from(value: crate::typed_ast::ElementSpecTy) -> Self {
654        match value {
655            crate::typed_ast::ElementSpecTy::TypeSpec(ty) => Self::TypeSpec(ty.into()),
656            crate::typed_ast::ElementSpecTy::ConstrTypeDcl(constr) => {
657                Self::ConstrTypeDcl(constr.into())
658            }
659        }
660    }
661}
662
663impl From<crate::typed_ast::SwitchTypeSpec> for SwitchTypeSpec {
664    fn from(value: crate::typed_ast::SwitchTypeSpec) -> Self {
665        match value {
666            crate::typed_ast::SwitchTypeSpec::IntegerType(integer_type) => {
667                Self::IntegerType(integer_type.into())
668            }
669            crate::typed_ast::SwitchTypeSpec::CharType(_) => Self::CharType,
670            crate::typed_ast::SwitchTypeSpec::WideCharType(_) => Self::WideCharType,
671            crate::typed_ast::SwitchTypeSpec::BooleanType(_) => Self::BooleanType,
672            crate::typed_ast::SwitchTypeSpec::ScopedName(scoped_name) => {
673                Self::ScopedName(scoped_name.into())
674            }
675            crate::typed_ast::SwitchTypeSpec::OctetType(_) => Self::OctetType,
676        }
677    }
678}
679
680fn declarator_name(value: &Declarator) -> &str {
681    match value {
682        Declarator::SimpleDeclarator(value) => &value.0,
683        Declarator::ArrayDeclarator(value) => &value.ident,
684    }
685}
686
687impl From<crate::typed_ast::BitsetDcl> for BitsetDcl {
688    fn from(value: crate::typed_ast::BitsetDcl) -> Self {
689        let mut field = Vec::new();
690        for bitfield in value.field {
691            let pos = bitfield.spec.pos;
692            let ty = bitfield.spec.dst_ty.map(Into::into);
693            for ident in bitfield.ident {
694                field.push(BitField {
695                    ident: ident.0,
696                    pos: pos.clone().into(),
697                    ty: ty.clone(),
698                });
699            }
700        }
701
702        Self {
703            annotations: vec![],
704            ident: value.ident.0,
705            parent: value.parent.map(Into::into),
706            field,
707        }
708    }
709}
710
711impl From<crate::typed_ast::DestinationType> for BitFieldType {
712    fn from(value: crate::typed_ast::DestinationType) -> Self {
713        match value {
714            crate::typed_ast::DestinationType::BooleanType(_) => Self::Bool,
715            crate::typed_ast::DestinationType::OctetType(_) => Self::Octec,
716            crate::typed_ast::DestinationType::IntegerType(integer_type) => {
717                if matches!(integer_type, crate::typed_ast::IntegerType::SignedInt(_)) {
718                    Self::SignedInt
719                } else {
720                    Self::UnsignedInt
721                }
722            }
723        }
724    }
725}
726
727impl From<crate::typed_ast::BitmaskDcl> for BitmaskDcl {
728    fn from(value: crate::typed_ast::BitmaskDcl) -> Self {
729        Self {
730            annotations: vec![],
731            ident: value.ident.0,
732            value: value.value.into_iter().map(Into::into).collect(),
733        }
734    }
735}
736
737impl From<crate::typed_ast::BitValue> for BitValue {
738    fn from(value: crate::typed_ast::BitValue) -> Self {
739        Self {
740            annotations: expand_annotations(value.annotations),
741            ident: value.ident.0,
742        }
743    }
744}