Skip to main content

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}