1use core::{
17 fmt::Display,
18 ops::{Deref, DerefMut},
19};
20
21use alloc::{boxed::Box, vec::Vec};
22use enumflags2::BitFlags;
23
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct Declaration<'src> {
26 pub base_type: QualifiedType<'src>,
27 pub declarator: Declarator<'src>,
28}
29
30impl<'src> From<(QualifiedType<'src>, Declarator<'src>)> for Declaration<'src> {
32 fn from((base_type, declarator): (QualifiedType<'src>, Declarator<'src>)) -> Self {
33 Declaration {
34 base_type,
35 declarator,
36 }
37 }
38}
39
40#[derive(Debug, Copy, Clone, PartialEq, Eq, parse_display::Display)]
41pub enum Type<'src> {
42 #[display("{0}")]
43 Primitive(PrimitiveType),
44 #[display("{0} {1}")]
45 Record(RecordKind, &'src str),
46 }
48
49#[derive(Debug, Copy, Clone, PartialEq, Eq, parse_display::Display)]
50#[display("{0}{1}")]
51pub struct QualifiedType<'src>(pub TypeQualifiers, pub Type<'src>);
52
53impl<'src> From<(TypeQualifiers, Type<'src>)> for QualifiedType<'src> {
54 fn from((qualifiers, ty): (TypeQualifiers, Type<'src>)) -> Self {
55 QualifiedType(qualifiers, ty)
56 }
57}
58
59impl<'src> From<Type<'src>> for QualifiedType<'src> {
60 fn from(ty: Type<'src>) -> Self {
61 QualifiedType(TypeQualifiers::default(), ty)
62 }
63}
64
65#[derive(Debug, Copy, Clone, PartialEq, Eq, parse_display::Display)]
67#[display(style = "title case")]
68#[enumflags2::bitflags]
69#[repr(u8)]
70pub enum TypeQualifier {
71 Const,
73 Volatile,
75 Restrict,
77}
78
79#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
81pub struct TypeQualifiers(pub BitFlags<TypeQualifier>);
82
83impl Deref for TypeQualifiers {
84 type Target = BitFlags<TypeQualifier>;
85
86 fn deref(&self) -> &Self::Target {
87 &self.0
88 }
89}
90
91impl DerefMut for TypeQualifiers {
92 fn deref_mut(&mut self) -> &mut Self::Target {
93 &mut self.0
94 }
95}
96
97impl Display for TypeQualifiers {
116 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
117 self.0.iter().enumerate().try_for_each(|(i, qualifier)| {
118 if i == 0 {
119 write!(f, "{qualifier}")
120 } else {
121 write!(f, " {qualifier}")
122 }
123 })
124 }
125}
126
127impl chumsky::container::Container<TypeQualifier> for TypeQualifiers {
128 fn push(&mut self, item: TypeQualifier) {
129 self.insert(item);
130 }
131}
132
133#[derive(Debug, Copy, Clone, PartialEq, Eq, parse_display::Display, parse_display::FromStr)]
134#[display(style = "title case")]
135pub enum RecordKind {
136 Union,
137 Struct,
138 Enum,
139}
140
141#[derive(Debug, Copy, Clone, PartialEq, Eq, parse_display::Display)]
142pub struct PrimitiveType(pub(crate) &'static str);
143
144impl AsRef<str> for PrimitiveType {
145 fn as_ref(&self) -> &str {
146 self.0
147 }
148}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub enum Declarator<'src> {
152 Anonymous,
155 Ident(&'src str),
156 Ptr(Box<Declarator<'src>>, TypeQualifiers),
157 Array(Box<Declarator<'src>>, Option<usize>),
158 Function {
159 func: Box<Declarator<'src>>,
160 params: Vec<Declaration<'src>>,
161 },
162}
163
164#[cfg(test)]
165mod tests {
166 use alloc::string::ToString;
167
168 use super::*;
169
170 #[test]
171 fn test_primitive_type_as_ref() {
172 let int_type = PrimitiveType("int");
173 assert_eq!(AsRef::<str>::as_ref(&int_type), "int");
174 }
175
176 #[test]
177 fn type_qualifiers_display() {
178 let mut qualifiers = TypeQualifiers::default();
179 assert_eq!(qualifiers.to_string(), "");
180
181 qualifiers.insert(TypeQualifier::Const);
182 assert_eq!(qualifiers.to_string(), "const");
183
184 qualifiers.insert(TypeQualifier::Volatile);
185 assert_eq!(qualifiers.to_string(), "const volatile");
186 }
187}