macho_header_syntax/ast.rs
1//! Typed header syntax.
2
3use std::fmt;
4
5/// The source language used to parse or render a header.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Language {
8 /// ISO C syntax.
9 C,
10 /// C++ syntax.
11 Cpp,
12 /// Objective-C syntax.
13 ObjectiveC,
14}
15
16/// A validated source-language identifier.
17#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct Identifier(String);
19
20impl Identifier {
21 /// Creates an identifier when `value` follows C-family identifier rules.
22 pub fn new(value: impl Into<String>) -> Option<Self> {
23 let value = value.into();
24 let mut chars = value.chars();
25 let first = chars.next()?;
26 if !(first == '_' || first.is_ascii_alphabetic())
27 || !chars.all(|ch| ch == '_' || ch.is_ascii_alphanumeric())
28 {
29 return None;
30 }
31 Some(Self(value))
32 }
33
34 /// Borrows the identifier text.
35 pub fn as_str(&self) -> &str {
36 &self.0
37 }
38}
39
40impl fmt::Display for Identifier {
41 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
42 formatter.write_str(&self.0)
43 }
44}
45
46/// A non-empty qualified identifier path.
47#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
48pub struct IdentifierPath(Vec<Identifier>);
49
50impl IdentifierPath {
51 /// Creates a non-empty identifier path.
52 pub fn new(values: Vec<Identifier>) -> Option<Self> {
53 (!values.is_empty()).then_some(Self(values))
54 }
55
56 /// Creates a path by splitting a C++ qualified name.
57 pub fn parse(value: &str) -> Option<Self> {
58 let values = value
59 .trim()
60 .trim_start_matches("::")
61 .split("::")
62 .map(str::trim)
63 .map(Identifier::new)
64 .collect::<Option<Vec<_>>>()?;
65 Self::new(values)
66 }
67
68 /// Borrows the path components.
69 pub fn components(&self) -> &[Identifier] {
70 &self.0
71 }
72
73 /// Borrows the terminal identifier.
74 pub fn last(&self) -> &Identifier {
75 self.0.last().expect("IdentifierPath is non-empty")
76 }
77}
78
79/// Built-in C-family scalar types.
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
81pub enum BuiltinType {
82 /// `void`.
83 Void,
84 /// `bool` or `_Bool`.
85 Bool,
86 /// `char`.
87 Char,
88 /// `signed char`.
89 SignedChar,
90 /// `unsigned char`.
91 UnsignedChar,
92 /// `short`.
93 Short,
94 /// `unsigned short`.
95 UnsignedShort,
96 /// `int`.
97 Int,
98 /// `unsigned int`.
99 UnsignedInt,
100 /// `long`.
101 Long,
102 /// `unsigned long`.
103 UnsignedLong,
104 /// `long long`.
105 LongLong,
106 /// `unsigned long long`.
107 UnsignedLongLong,
108 /// Signed 128-bit integer.
109 Int128,
110 /// Unsigned 128-bit integer.
111 UnsignedInt128,
112 /// `float`.
113 Float,
114 /// `double`.
115 Double,
116 /// `long double`.
117 LongDouble,
118}
119
120/// The namespace used to resolve a named type.
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
122pub enum NamedTypeTag {
123 /// Typedef or ordinary named type.
124 Typedef,
125 /// C struct tag.
126 Struct,
127 /// C union tag.
128 Union,
129 /// Enumeration tag.
130 Enum,
131 /// C++ class name.
132 Class,
133 /// Objective-C protocol name.
134 Protocol,
135}
136
137/// C/C++ type qualifiers.
138#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
139pub struct TypeQualifiers {
140 /// Whether `const` is present.
141 pub is_const: bool,
142 /// Whether `volatile` is present.
143 pub is_volatile: bool,
144 /// Whether `restrict` is present.
145 pub is_restrict: bool,
146}
147
148/// C++ reference kind.
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
150pub enum ReferenceKind {
151 /// Lvalue reference (`&`).
152 Lvalue,
153 /// Rvalue reference (`&&`).
154 Rvalue,
155}
156
157/// Whether a function's parameter list is known.
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
159pub enum ParameterState {
160 /// C's unspecified `()` parameter list.
161 Unspecified,
162 /// A known parameter list.
163 Known,
164}
165
166/// Function calling convention.
167#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
168pub enum CallingConvention {
169 /// C ABI.
170 C,
171 /// Swift ABI.
172 Swift,
173 /// Objective-C method ABI.
174 ObjectiveCMethod,
175 /// Microsoft thiscall.
176 Thiscall,
177 /// Vectorcall.
178 Vectorcall,
179 /// ARM procedure call standard.
180 Aapcs,
181 /// ARM hard-float procedure call standard.
182 AapcsVfp,
183 /// An observed but unidentified convention.
184 Unknown,
185}
186
187/// C++ function qualifiers.
188#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
189pub struct FunctionQualifiers {
190 /// Whether the member function is `const`.
191 pub is_const: bool,
192 /// Whether the member function is `volatile`.
193 pub is_volatile: bool,
194 /// Optional reference qualifier.
195 pub reference: Option<ReferenceKind>,
196 /// `None` means the noexcept state is unknown.
197 pub noexcept: Option<bool>,
198}
199
200/// A template argument.
201#[derive(Debug, Clone, PartialEq, Eq, Hash)]
202pub enum TemplateArgument {
203 /// Type argument.
204 Type(Type),
205 /// Integer non-type argument.
206 Integer(i64),
207 /// Identifier non-type argument.
208 Identifier(IdentifierPath),
209}
210
211/// A named function parameter.
212#[derive(Debug, Clone, PartialEq, Eq, Hash)]
213pub struct Parameter {
214 /// Stable parameter name.
215 pub name: Identifier,
216 /// Parameter type.
217 pub ty: Type,
218}
219
220/// A fully typed header type.
221#[derive(Debug, Clone, PartialEq, Eq, Hash)]
222pub enum Type {
223 /// Built-in scalar type.
224 Builtin(BuiltinType),
225 /// Named type.
226 Named {
227 /// Tag namespace.
228 tag: NamedTypeTag,
229 /// Qualified name.
230 path: IdentifierPath,
231 /// Template arguments.
232 template_arguments: Vec<TemplateArgument>,
233 },
234 /// Pointer type.
235 Pointer {
236 /// Pointee type.
237 pointee: Box<Type>,
238 /// Pointer qualifiers.
239 qualifiers: TypeQualifiers,
240 },
241 /// C++ reference type.
242 Reference {
243 /// Referenced type.
244 target: Box<Type>,
245 /// Reference category.
246 kind: ReferenceKind,
247 },
248 /// Array type.
249 Array {
250 /// Element type.
251 element: Box<Type>,
252 /// Constant element count, when known.
253 count: Option<u64>,
254 },
255 /// Function type.
256 Function {
257 /// Return type.
258 return_type: Box<Type>,
259 /// Parameters.
260 parameters: Vec<Parameter>,
261 /// Whether the parameter list is known.
262 parameter_state: ParameterState,
263 /// Whether the function is variadic.
264 variadic: bool,
265 /// Calling convention.
266 calling_convention: CallingConvention,
267 /// C++ function qualifiers.
268 qualifiers: FunctionQualifiers,
269 },
270 /// Objective-C object pointer surface.
271 ObjectiveCObject {
272 /// Optional class name; absent represents `id`.
273 name: Option<Identifier>,
274 /// Protocol qualifications.
275 protocols: Vec<Identifier>,
276 /// Object-pointer qualifiers.
277 qualifiers: TypeQualifiers,
278 },
279 /// Objective-C block signature.
280 ObjectiveCBlock(Box<Type>),
281}
282
283/// Storage-class specifier.
284#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
285pub enum StorageClass {
286 /// No explicit storage class.
287 None,
288 /// `extern`.
289 Extern,
290 /// `static`.
291 Static,
292 /// Thread-local storage.
293 ThreadLocal,
294}
295
296/// Language linkage attached to a declaration.
297#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
298pub enum Linkage {
299 /// C linkage.
300 C,
301 /// C++ linkage.
302 Cpp,
303 /// Objective-C linkage.
304 ObjectiveC,
305}
306
307/// Record declaration kind.
308#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
309pub enum RecordKind {
310 /// Struct.
311 Struct,
312 /// Union.
313 Union,
314 /// Class.
315 Class,
316 /// Enumeration.
317 Enum,
318}
319
320/// Member access.
321#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
322pub enum Access {
323 /// Public access.
324 Public,
325 /// Protected access.
326 Protected,
327 /// Private access.
328 Private,
329 /// Access was not stated.
330 Unspecified,
331}
332
333/// A record base.
334#[derive(Debug, Clone, PartialEq, Eq, Hash)]
335pub struct Base {
336 /// Base type.
337 pub ty: Type,
338 /// Inheritance access.
339 pub access: Access,
340 /// Whether inheritance is virtual.
341 pub is_virtual: bool,
342}
343
344/// A record field.
345#[derive(Debug, Clone, PartialEq, Eq, Hash)]
346pub struct Field {
347 /// Field name.
348 pub name: Identifier,
349 /// Field type.
350 pub ty: Type,
351 /// Byte offset when recovered.
352 pub offset: Option<u64>,
353 /// Bit-field width when applicable.
354 pub bit_width: Option<u32>,
355 /// Member access.
356 pub access: Access,
357}
358
359/// Objective-C method kind.
360#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
361pub enum MethodKind {
362 /// Instance method (`-`).
363 Instance,
364 /// Class method (`+`).
365 Class,
366}
367
368/// Objective-C method declaration.
369#[derive(Debug, Clone, PartialEq, Eq, Hash)]
370pub struct ObjectiveCMethod {
371 /// Instance or class method.
372 pub kind: MethodKind,
373 /// Complete selector spelling.
374 pub selector: String,
375 /// Return type.
376 pub return_type: Type,
377 /// Selector parameters.
378 pub parameters: Vec<Parameter>,
379 /// Required/optional state when declared in a protocol.
380 pub required: Option<bool>,
381}
382
383/// Objective-C ivar visibility.
384#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
385pub enum ObjectiveCAccess {
386 /// Public ivar.
387 Public,
388 /// Protected ivar.
389 Protected,
390 /// Private ivar.
391 Private,
392 /// Package-visible ivar.
393 Package,
394}
395
396/// Objective-C instance-variable declaration.
397#[derive(Debug, Clone, PartialEq, Eq, Hash)]
398pub struct ObjectiveCIvar {
399 /// Ivar name.
400 pub name: Identifier,
401 /// Complete encoded type.
402 pub ty: Type,
403 /// Runtime visibility.
404 pub access: ObjectiveCAccess,
405}
406
407/// Objective-C property attribute supported by the deterministic renderer.
408#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
409pub enum ObjectiveCPropertyAttribute {
410 /// Read-only property.
411 Readonly,
412 /// Read-write property.
413 Readwrite,
414 /// Copy ownership.
415 Copy,
416 /// Retain ownership.
417 Retain,
418 /// Strong ownership.
419 Strong,
420 /// Weak ownership.
421 Weak,
422 /// Assign ownership.
423 Assign,
424 /// Atomic property.
425 Atomic,
426 /// Non-atomic property.
427 Nonatomic,
428 /// Dynamically implemented property.
429 Dynamic,
430 /// Class property.
431 Class,
432}
433
434/// Objective-C property declaration.
435#[derive(Debug, Clone, PartialEq, Eq, Hash)]
436pub struct ObjectiveCProperty {
437 /// Property name.
438 pub name: Identifier,
439 /// Complete property type.
440 pub ty: Type,
441 /// Canonically ordered attributes.
442 pub attributes: Vec<ObjectiveCPropertyAttribute>,
443}
444
445/// Objective-C forward-declaration kind.
446#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
447pub enum ObjectiveCForwardKind {
448 /// Class forward declaration.
449 Class,
450 /// Protocol forward declaration.
451 Protocol,
452}
453
454/// A top-level typed declaration.
455#[derive(Debug, Clone, PartialEq, Eq, Hash)]
456pub enum Decl {
457 /// Function declaration.
458 Function {
459 /// Name.
460 name: Identifier,
461 /// Function type.
462 signature: Type,
463 /// Storage class.
464 storage: StorageClass,
465 /// Language linkage.
466 linkage: Linkage,
467 },
468 /// Variable declaration.
469 Variable {
470 /// Name.
471 name: Identifier,
472 /// Variable type.
473 ty: Type,
474 /// Storage class.
475 storage: StorageClass,
476 /// Language linkage.
477 linkage: Linkage,
478 },
479 /// Complete record declaration.
480 Record {
481 /// Record kind.
482 kind: RecordKind,
483 /// Qualified name.
484 path: IdentifierPath,
485 /// Base classes.
486 bases: Vec<Base>,
487 /// Data fields.
488 fields: Vec<Field>,
489 /// Nested declarations.
490 members: Vec<Decl>,
491 },
492 /// Incomplete record declaration.
493 Forward {
494 /// Record kind.
495 kind: RecordKind,
496 /// Qualified name.
497 path: IdentifierPath,
498 },
499 /// Type alias.
500 Alias {
501 /// Alias name.
502 path: IdentifierPath,
503 /// Aliased type.
504 target: Type,
505 },
506 /// Objective-C interface.
507 ObjectiveCInterface {
508 /// Class name.
509 name: Identifier,
510 /// Optional superclass.
511 superclass: Option<Identifier>,
512 /// Adopted protocols.
513 protocols: Vec<Identifier>,
514 /// Instance variables.
515 ivars: Vec<ObjectiveCIvar>,
516 /// Methods.
517 methods: Vec<ObjectiveCMethod>,
518 /// Properties.
519 properties: Vec<ObjectiveCProperty>,
520 },
521 /// Objective-C category.
522 ObjectiveCCategory {
523 /// Category name.
524 name: Identifier,
525 /// Extended class.
526 extended_class: Identifier,
527 /// Adopted protocols.
528 protocols: Vec<Identifier>,
529 /// Methods.
530 methods: Vec<ObjectiveCMethod>,
531 /// Properties.
532 properties: Vec<ObjectiveCProperty>,
533 },
534 /// Objective-C protocol.
535 ObjectiveCProtocol {
536 /// Protocol name.
537 name: Identifier,
538 /// Inherited protocols.
539 protocols: Vec<Identifier>,
540 /// Methods.
541 methods: Vec<ObjectiveCMethod>,
542 /// Properties.
543 properties: Vec<ObjectiveCProperty>,
544 },
545 /// Objective-C forward declarations.
546 ObjectiveCForward {
547 /// Forward kind.
548 kind: ObjectiveCForwardKind,
549 /// Declared names.
550 names: Vec<Identifier>,
551 },
552}
553
554impl Decl {
555 /// Returns the declaration's terminal name when it has one.
556 pub fn name(&self) -> Option<&Identifier> {
557 match self {
558 Self::Function { name, .. }
559 | Self::Variable { name, .. }
560 | Self::ObjectiveCInterface { name, .. }
561 | Self::ObjectiveCCategory { name, .. }
562 | Self::ObjectiveCProtocol { name, .. } => Some(name),
563 Self::Record { path, .. } | Self::Forward { path, .. } | Self::Alias { path, .. } => {
564 Some(path.last())
565 }
566 Self::ObjectiveCForward { .. } => None,
567 }
568 }
569}
570
571/// A parsed header translation unit.
572#[derive(Debug, Clone, PartialEq, Eq, Hash)]
573pub struct TranslationUnit {
574 /// Source language.
575 pub language: Language,
576 /// Typed declarations in source order.
577 pub declarations: Vec<Decl>,
578 /// Source span for each declaration when the unit came from the parser.
579 ///
580 /// Programmatically constructed units may leave this empty. A parsed unit
581 /// always has exactly one entry per declaration; declarations lowered from
582 /// one multi-declarator syntax node share that node's span.
583 pub declaration_spans: Vec<crate::SourceSpan>,
584}