Skip to main content

xidl_parser/hir/
struct_dcl.rs

1use super::*;
2use serde::{Deserialize, Serialize};
3use std::fmt;
4
5#[derive(Debug, Serialize, Deserialize, Clone)]
6pub struct StructForwardDcl {
7    pub annotations: Vec<Annotation>,
8    pub ident: String,
9}
10
11#[derive(Serialize, Deserialize, Clone)]
12pub struct StructDcl {
13    pub annotations: Vec<Annotation>,
14    pub ident: String,
15    pub parent: Vec<ScopedName>,
16    pub member: Vec<Member>,
17    /// Members inherited from the single base struct, flattened into this
18    /// struct's wire shape. Populated by semantic analysis.
19    #[serde(default, skip_serializing_if = "Vec::is_empty")]
20    pub inherited: Vec<Member>,
21}
22
23impl fmt::Debug for StructDcl {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        let mut debug = f.debug_struct("StructDcl");
26        debug
27            .field("annotations", &self.annotations)
28            .field("ident", &self.ident)
29            .field("parent", &self.parent)
30            .field("member", &self.member);
31        // Structs without a base keep their historical debug shape so stored
32        // snapshots describe only declarations that carry inherited members.
33        if !self.inherited.is_empty() {
34            debug.field("inherited", &self.inherited);
35        }
36        debug.finish()
37    }
38}
39
40#[derive(Debug, Serialize, Deserialize, Clone)]
41pub struct Member {
42    pub annotations: Vec<Annotation>,
43    pub ty: TypeSpec,
44    pub ident: Vec<Declarator>,
45    pub default: Option<Default>,
46    pub field_id: Option<u32>,
47    pub recursive: bool,
48}
49
50#[derive(Debug, Serialize, Deserialize, Clone)]
51pub struct Default(pub ConstExpr);
52
53impl Member {
54    pub fn is_optional(&self) -> bool {
55        self.annotations.iter().any(|annotation| match annotation {
56            Annotation::Optional { .. } => true,
57            Annotation::ScopedName { name, .. } => name
58                .name
59                .last()
60                .map(|value| value.eq_ignore_ascii_case("optional"))
61                .unwrap_or(false),
62            _ => false,
63        })
64    }
65}
66
67impl StructDcl {
68    /// Members of this struct in wire order: inherited members first, then its
69    /// own members.
70    ///
71    /// Inherited members are the single base struct's fields, copied into this
72    /// struct by semantic analysis. A target that renders a flattened JSON shape
73    /// must use this iterator instead of [`Self::member`].
74    pub fn members(&self) -> impl Iterator<Item = &Member> {
75        self.inherited.iter().chain(self.member.iter())
76    }
77}
78
79impl From<crate::typed_ast::StructDef> for StructDcl {
80    fn from(value: crate::typed_ast::StructDef) -> Self {
81        let mut members = value
82            .member
83            .into_iter()
84            .map(Into::into)
85            .collect::<Vec<Member>>();
86        for (index, member) in members.iter_mut().enumerate() {
87            if member.field_id.is_none() {
88                member.field_id = Some((index + 1) as u32);
89            }
90        }
91        Self {
92            annotations: vec![],
93            ident: value.ident.0,
94            parent: value.parent.into_iter().map(Into::into).collect(),
95            member: members,
96            inherited: Vec::new(),
97        }
98    }
99}
100
101impl From<crate::typed_ast::Member> for Member {
102    fn from(value: crate::typed_ast::Member) -> Self {
103        let annotations = expand_annotations(value.annotations);
104        let field_id = annotation_id_value(&annotations);
105        Self {
106            annotations,
107            ty: value.ty.into(),
108            ident: value.ident.0.into_iter().map(Into::into).collect(),
109            default: value.default.map(Into::into),
110            field_id,
111            recursive: false,
112        }
113    }
114}
115
116impl From<crate::typed_ast::StructForwardDcl> for StructForwardDcl {
117    fn from(typed_ast: crate::typed_ast::StructForwardDcl) -> Self {
118        Self {
119            annotations: vec![],
120            ident: typed_ast.ident.0,
121        }
122    }
123}
124
125impl From<crate::typed_ast::Default> for Default {
126    fn from(value: crate::typed_ast::Default) -> Self {
127        Self(value.0.into())
128    }
129}