Skip to main content

rsbinder_aidl/
parser.rs

1// Copyright 2022 Jeff Kim <hiking90@gmail.com>
2// SPDX-License-Identifier: Apache-2.0
3
4// #![allow(clippy::missing_const_for_fn)]
5
6use std::cell::RefCell;
7use std::collections::HashMap;
8
9use crate::error::{pest_error_to_diagnostic, AidlError, ParseError};
10
11use convert_case::{Case, Casing};
12
13use pest::Parser;
14#[derive(pest_derive::Parser)]
15#[grammar = "aidl.pest"]
16pub struct AIDLParser;
17
18use crate::const_expr::{ConstExpr, ValueType};
19use crate::type_generator;
20use crate::Namespace;
21
22#[derive(Debug, Clone)]
23pub enum SymbolType {
24    EnumMember,
25    InterfaceConstant,
26    // Future expansion: ParcelableDefault, Variable, etc.
27}
28
29#[derive(Debug, Clone)]
30pub struct Symbol {
31    #[allow(dead_code)]
32    pub name: String,
33    pub value: crate::const_expr::ConstExpr,
34    #[allow(dead_code)]
35    pub symbol_type: SymbolType,
36    #[allow(dead_code)]
37    pub namespace: Option<String>,
38}
39
40thread_local! {
41    static DECLARATION_MAP: RefCell<HashMap<Namespace, Declaration>> = RefCell::new(HashMap::new());
42    #[allow(clippy::missing_const_for_thread_local)]
43    static NAMESPACE_STACK: RefCell<Vec<Namespace>> = RefCell::new(Vec::new());
44    static DOCUMENT: RefCell<Document> = RefCell::new(Document::new());
45
46    // Universal Symbol Table - supports all types of named constants
47    static SYMBOL_TABLE: RefCell<HashMap<String, Symbol>> = RefCell::new(HashMap::new());
48
49    // Filename and source text of the source currently being parsed (used for error message generation)
50    #[allow(clippy::missing_const_for_thread_local)]
51    static CURRENT_SOURCE_NAME: RefCell<String> = RefCell::new(String::new());
52    #[allow(clippy::missing_const_for_thread_local)]
53    static CURRENT_SOURCE_TEXT: RefCell<String> = RefCell::new(String::new());
54}
55
56/// Helper that creates a ParseError using the same thread-local source info as SourceGuard.
57fn make_parse_error(message: impl Into<String>, start: usize, end: usize) -> AidlError {
58    let filename = CURRENT_SOURCE_NAME.with(|name| name.borrow().clone());
59    let source = CURRENT_SOURCE_TEXT.with(|text| text.borrow().clone());
60    AidlError::from(ParseError {
61        src: miette::NamedSource::new(filename, source),
62        span: miette::SourceSpan::new(start.into(), end - start),
63        message: message.into(),
64        help: None,
65    })
66}
67
68/// Context struct holding the filename and source text of a file to be parsed.
69/// Passed to `parse_document()` so that file information is included in error diagnostics.
70#[derive(Debug, Clone)]
71pub struct SourceContext {
72    pub filename: String,
73    pub source: String,
74}
75
76impl SourceContext {
77    pub fn new(filename: impl Into<String>, source: impl Into<String>) -> Self {
78        Self {
79            filename: filename.into(),
80            source: source.into(),
81        }
82    }
83}
84
85/// RAII guard: sets the thread-local source context on creation and clears it
86/// automatically on drop, ensuring cleanup on both error-return and panic paths.
87pub struct SourceGuard;
88
89impl SourceGuard {
90    pub fn new(filename: &str, source: &str) -> Self {
91        CURRENT_SOURCE_NAME.with(|name| *name.borrow_mut() = filename.to_string());
92        CURRENT_SOURCE_TEXT.with(|text| *text.borrow_mut() = source.to_string());
93        SourceGuard
94    }
95}
96
97impl Drop for SourceGuard {
98    fn drop(&mut self) {
99        CURRENT_SOURCE_NAME.with(|name| name.borrow_mut().clear());
100        CURRENT_SOURCE_TEXT.with(|text| text.borrow_mut().clear());
101    }
102}
103
104/// Returns the filename of the currently active source context.
105pub fn current_source_name() -> String {
106    CURRENT_SOURCE_NAME.with(|name| name.borrow().clone())
107}
108
109/// Returns the source text of the currently active source context.
110pub fn current_source_text() -> String {
111    CURRENT_SOURCE_TEXT.with(|text| text.borrow().clone())
112}
113
114pub struct NamespaceGuard();
115
116impl NamespaceGuard {
117    pub fn new(ns: &Namespace) -> Self {
118        NAMESPACE_STACK.with(|vec| {
119            vec.borrow_mut().push(ns.clone());
120        });
121        Self()
122    }
123}
124
125impl Drop for NamespaceGuard {
126    fn drop(&mut self) {
127        NAMESPACE_STACK.with(|vec| {
128            vec.borrow_mut().pop();
129        });
130    }
131}
132
133pub fn current_namespace() -> Namespace {
134    NAMESPACE_STACK.with(|stack| stack.borrow().last().cloned().unwrap_or_default())
135}
136
137pub fn set_current_document(document: &Document) {
138    DOCUMENT.with(|doc| {
139        let mut doc = doc.borrow_mut();
140
141        doc.package = document.package.clone();
142        doc.imports = document.imports.clone();
143    })
144}
145
146fn make_ns_candidate(ns: &Namespace, name: &Namespace) -> Vec<Namespace> {
147    let mut res = Vec::new();
148
149    let mut curr_ns = ns.clone();
150    curr_ns.push_ns(name);
151    res.push(curr_ns.clone());
152
153    if name.ns.len() > 1 {
154        curr_ns.pop(); // Remove the last name in case of IntEnum.Foo. Removed the Foo.
155        res.push(curr_ns);
156    }
157
158    res
159}
160
161#[derive(Debug)]
162pub struct LookupDecl {
163    pub decl: Declaration,
164    pub ns: Namespace,
165    pub name: Namespace,
166}
167
168pub fn lookup_decl_from_name(name: &str, style: &str) -> Option<LookupDecl> {
169    let mut namespace = Namespace::new(name, style);
170
171    let mut ns_vec = Vec::new();
172
173    // 1, check if the type exists in the current namespace.
174    let mut curr_ns = current_namespace();
175    ns_vec.append(&mut make_ns_candidate(&curr_ns, &namespace));
176
177    curr_ns.pop(); // For parent namespace
178    ns_vec.append(&mut make_ns_candidate(&curr_ns, &namespace));
179
180    // 2. check if the type exists in the imports from the current document.
181    DOCUMENT.with(|curr_doc| {
182        let curr_doc = curr_doc.borrow();
183
184        if let Some(package) = &curr_doc.package {
185            let package_ns = Namespace::new(package, Namespace::AIDL);
186            ns_vec.append(&mut make_ns_candidate(&package_ns, &namespace));
187        }
188
189        if let Some(imported) = curr_doc.imports.get(&namespace.ns[0]) {
190            let mut new_ns = Namespace::new(imported, Namespace::AIDL);
191            new_ns.ns.extend_from_slice(&namespace.ns[1..]);
192            ns_vec.push(new_ns);
193        }
194    });
195
196    let (decl, ns) = DECLARATION_MAP.with(|hashmap| {
197        for ns in &ns_vec {
198            if let Some(decl) = hashmap.borrow().get(ns) {
199                return Some((decl.clone(), ns.clone()));
200            }
201        }
202
203        let curr_ns = current_namespace();
204        if let Some(decl) = hashmap.borrow().get(&curr_ns) {
205            return Some((decl.clone(), curr_ns));
206        }
207
208        None
209    })?;
210
211    // leave max 2 items because the other items are for name space.
212    if namespace.ns.len() > 2 {
213        namespace.ns.drain(0..namespace.ns.len() - 2);
214    }
215
216    Some(LookupDecl {
217        decl,
218        ns,
219        name: namespace,
220    })
221}
222
223fn make_const_expr(const_expr: Option<&ConstExpr>, lookup_decl: &LookupDecl) -> ConstExpr {
224    if let Some(expr) = const_expr {
225        expr.clone()
226    } else {
227        let ns = current_namespace().relative_mod(&lookup_decl.ns);
228
229        let name = if !ns.is_empty() {
230            format!(
231                "{}{}{}",
232                ns,
233                Namespace::RUST,
234                lookup_decl.name.to_string(Namespace::RUST)
235            )
236        } else {
237            lookup_decl.name.to_string(Namespace::RUST)
238        };
239        ConstExpr::new(ValueType::Name(name))
240    }
241}
242
243fn lookup_name_from_decl(decl: &Declaration, lookup_decl: &LookupDecl) -> Option<ConstExpr> {
244    let lookup_ident = lookup_decl.name.ns.last().unwrap().to_owned();
245    match decl {
246        Declaration::Variable(decl) => {
247            if decl.identifier == lookup_ident {
248                Some(make_const_expr(decl.const_expr.as_ref(), lookup_decl))
249            } else {
250                None
251            }
252        }
253        Declaration::Interface(ref decl) => {
254            for var in &decl.constant_list {
255                if var.identifier == lookup_ident {
256                    return Some(make_const_expr(var.const_expr.as_ref(), lookup_decl));
257                }
258            }
259            lookup_name_members(&decl.members, lookup_decl)
260        }
261
262        Declaration::Parcelable(ref decl) => lookup_name_members(&decl.members, lookup_decl),
263
264        Declaration::Enum(ref decl) => {
265            for enumerator in &decl.enumerator_list {
266                if enumerator.identifier == lookup_ident {
267                    return Some(make_const_expr(None, lookup_decl));
268                }
269            }
270            lookup_name_members(&decl.members, lookup_decl)
271        }
272
273        Declaration::Union(ref decl) => lookup_name_members(&decl.members, lookup_decl),
274    }
275}
276
277fn lookup_name_members(members: &Vec<Declaration>, lookup_decl: &LookupDecl) -> Option<ConstExpr> {
278    for decl in members {
279        if let Some(expr) = lookup_name_from_decl(decl, lookup_decl) {
280            return Some(expr);
281        }
282    }
283    None
284}
285
286// Universal symbol registration - supports all types of named constants
287pub fn register_symbol(
288    name: &str,
289    value: ConstExpr,
290    symbol_type: SymbolType,
291    namespace: Option<&str>,
292) {
293    let symbol = Symbol {
294        name: name.to_string(),
295        value,
296        symbol_type,
297        namespace: namespace.map(|s| s.to_string()),
298    };
299
300    SYMBOL_TABLE.with(|table| {
301        let mut table = table.borrow_mut();
302
303        // Register with simple name
304        table.insert(name.to_string(), symbol.clone());
305
306        // Also register with qualified name if namespace is provided
307        if let Some(ns) = namespace {
308            let qualified_name = format!("{}.{}", ns, name);
309            table.insert(qualified_name, symbol);
310        }
311    });
312}
313
314// Note: register_enum_member removed as it's not used
315// Use register_symbol directly with SymbolType::EnumMember
316
317// Enhanced name resolution with universal symbol table
318pub fn name_to_const_expr(name: &str) -> Option<ConstExpr> {
319    // First, try to resolve from universal symbol table (exact match)
320    let symbol_result =
321        SYMBOL_TABLE.with(|table| table.borrow().get(name).map(|symbol| symbol.value.clone()));
322
323    if symbol_result.is_some() {
324        return symbol_result;
325    }
326
327    // For dotted names, try namespace-aware declaration lookup before variant stripping.
328    // This ensures that qualified names like "ParcelableWithNested.Status.OK"
329    // are resolved with full namespace context rather than being stripped to
330    // shorter variants that may lose parent type information.
331    if name.contains('.') {
332        if let Some(lookup_decl) = lookup_decl_from_name(name, Namespace::AIDL) {
333            if let Some(expr) = lookup_name_from_decl(&lookup_decl.decl, &lookup_decl) {
334                return Some(expr);
335            }
336        }
337    }
338
339    // Try alternative name formats for cross-references
340    let alternative_formats = generate_name_variants(name);
341    for variant in alternative_formats {
342        let variant_result = SYMBOL_TABLE.with(|table| {
343            table
344                .borrow()
345                .get(&variant)
346                .map(|symbol| symbol.value.clone())
347        });
348        if variant_result.is_some() {
349            return variant_result;
350        }
351    }
352
353    // Fallback to original resolution
354    if let Some(lookup_decl) = lookup_decl_from_name(name, Namespace::AIDL) {
355        return lookup_name_from_decl(&lookup_decl.decl, &lookup_decl);
356    }
357
358    None
359}
360
361// Generate possible name variants for flexible resolution
362fn generate_name_variants(name: &str) -> Vec<String> {
363    let mut variants = Vec::new();
364
365    // Handle dot notation: "A.B.C" -> ["A.B.C", "B.C", "C"]
366    // Try progressively shorter prefixes to find the best qualified match
367    if name.contains('.') {
368        let parts: Vec<&str> = name.split('.').collect();
369        for i in 0..parts.len() {
370            variants.push(parts[i..].join("."));
371        }
372    } else {
373        // For simple names, try with current namespace context
374        let current_ns = current_namespace().to_string(crate::Namespace::AIDL);
375
376        if !current_ns.is_empty() {
377            variants.push(format!("{}.{}", current_ns, name));
378        }
379        variants.push(name.to_string());
380    }
381
382    variants
383}
384
385#[derive(Debug)]
386pub struct Document {
387    pub package: Option<String>,
388    pub imports: HashMap<String, String>,
389    pub decls: Vec<Declaration>,
390}
391
392impl Document {
393    fn new() -> Self {
394        Self {
395            package: None,
396            imports: HashMap::new(),
397            decls: Vec::new(),
398        }
399    }
400}
401
402#[derive(Debug, Default, Clone)]
403pub struct VariableDecl {
404    pub constant: bool,
405    pub annotation_list: Vec<Annotation>,
406    pub r#type: Type,
407    pub identifier: String,
408    pub const_expr: Option<ConstExpr>,
409}
410
411impl VariableDecl {
412    pub fn identifier(&self) -> String {
413        self.identifier.to_owned()
414    }
415
416    pub fn const_identifier(&self) -> String {
417        self.identifier.to_uppercase()
418    }
419
420    pub fn union_identifier(&self) -> String {
421        self.identifier.to_case(Case::UpperCamel)
422    }
423
424    pub fn member_init(&self) -> String {
425        "Default::default()".into()
426    }
427}
428
429#[derive(Debug, Default, Clone)]
430pub struct InterfaceDecl {
431    pub namespace: Namespace,
432    pub annotation_list: Vec<Annotation>,
433    pub oneway: bool,
434    pub name: String,
435    pub name_span: Option<(usize, usize)>,
436    pub method_list: Vec<MethodDecl>,
437    pub constant_list: Vec<VariableDecl>,
438    pub members: Vec<Declaration>,
439}
440
441impl InterfaceDecl {
442    pub fn pre_process(&mut self) {
443        for decl in &mut self.constant_list {
444            decl.const_expr = decl
445                .const_expr
446                .as_ref()
447                .map(|expr| expr.calculate().unwrap_or_else(|_| expr.clone()));
448        }
449    }
450}
451
452#[derive(Debug, Default, Clone)]
453pub struct ParcelableDecl {
454    pub annotation_list: Vec<Annotation>,
455    pub namespace: Namespace,
456    pub name: String,
457    pub type_params: Vec<String>,
458    pub cpp_header: String,
459    pub ndk_header: String,
460    pub rust_type: String,
461    pub members: Vec<Declaration>,
462    // pub name_dict: Option<HashMap<String, ConstExpr>>,
463}
464
465impl ParcelableDecl {
466    pub fn pre_process(&mut self) {
467        for decl in &mut self.members {
468            if let Declaration::Variable(decl) = decl {
469                decl.const_expr = decl
470                    .const_expr
471                    .as_ref()
472                    .map(|expr| expr.calculate().unwrap_or_else(|_| expr.clone()));
473            }
474        }
475    }
476}
477
478#[derive(Debug, Default, Clone)]
479pub enum Direction {
480    #[default]
481    None,
482    In,
483    Out,
484    Inout,
485}
486
487#[derive(Debug, Default, Clone)]
488pub struct Arg {
489    pub direction: Direction,
490    pub direction_span: Option<(usize, usize)>,
491    pub r#type: Type,
492    pub identifier: String,
493}
494
495impl Arg {
496    pub fn to_generator(&self) -> Result<type_generator::TypeGenerator, crate::error::AidlError> {
497        let generator = type_generator::TypeGenerator::new_with_type(&self.r#type)?;
498
499        Ok(generator
500            .direction_at(&self.direction, self.direction_span)?
501            .identifier(&self.identifier))
502    }
503
504    // fn arg_identifier(&self) -> String {
505    //     format!("_arg_{}", self.identifier)
506    // }
507
508    // pub fn to_string(&self, is_nullable: bool) -> (String, String, String, String) {
509    //     let param = self.arg_identifier();
510    //     let mut type_cast = self.r#type.type_cast();
511    //     let type_cloned = type_cast.clone();
512    //     type_cast.set_fn_nullable(is_nullable);
513    //     let def_arg = type_cast.fn_def_arg(&self.direction);
514    //     let arg = format!("{}: {}",
515    //         param.clone(), def_arg);
516    //     (param, arg, def_arg, type_cloned.return_type())
517    // }
518
519    pub fn is_mutable(&self) -> bool {
520        match self.direction {
521            Direction::Inout | Direction::Out => true,
522            Direction::In => false,
523            _ => false,
524        }
525    }
526}
527
528#[derive(Debug, Default, Clone)]
529pub struct MethodDecl {
530    pub annotation_list: Vec<Annotation>,
531    pub oneway: bool,
532    pub r#type: Type,
533    pub identifier: String,
534    pub identifier_span: Option<(usize, usize)>,
535    pub arg_list: Vec<Arg>,
536    pub intvalue: Option<i64>,
537    pub intvalue_span: Option<(usize, usize)>,
538}
539
540#[derive(Debug, Clone)]
541pub enum Declaration {
542    Parcelable(ParcelableDecl),
543    Interface(InterfaceDecl),
544    Enum(EnumDecl),
545    Union(UnionDecl),
546    Variable(VariableDecl),
547}
548
549impl Declaration {
550    pub fn is_variable(&self) -> Option<&VariableDecl> {
551        if let Declaration::Variable(decl) = self {
552            Some(decl)
553        } else {
554            None
555        }
556    }
557
558    pub fn namespace(&self) -> &Namespace {
559        match self {
560            Declaration::Parcelable(decl) => &decl.namespace,
561            Declaration::Interface(decl) => &decl.namespace,
562            Declaration::Enum(decl) => &decl.namespace,
563            Declaration::Union(decl) => &decl.namespace,
564            _ => unreachable!(),
565        }
566    }
567
568    pub fn set_namespace(&mut self, namespace: Namespace) {
569        match self {
570            Declaration::Parcelable(decl) => decl.namespace = namespace,
571            Declaration::Interface(decl) => decl.namespace = namespace,
572            Declaration::Enum(decl) => decl.namespace = namespace,
573            Declaration::Union(decl) => decl.namespace = namespace,
574            _ => unreachable!(),
575        }
576    }
577
578    pub fn name(&self) -> &str {
579        match self {
580            Declaration::Parcelable(decl) => &decl.name,
581            Declaration::Interface(decl) => &decl.name,
582            Declaration::Enum(decl) => &decl.name,
583            Declaration::Union(decl) => &decl.name,
584            _ => unreachable!(),
585        }
586    }
587
588    pub fn members_mut(&mut self) -> &mut Vec<Declaration> {
589        match self {
590            Declaration::Parcelable(decl) => &mut decl.members,
591            Declaration::Interface(decl) => &mut decl.members,
592            Declaration::Enum(decl) => &mut decl.members,
593            Declaration::Union(decl) => &mut decl.members,
594            _ => unreachable!(),
595        }
596    }
597}
598
599#[derive(Debug, Clone)]
600pub struct Parameter {
601    identifier: String,
602    const_expr: ConstExpr,
603}
604
605#[derive(Debug, Default, Clone)]
606pub struct Annotation {
607    pub annotation: String,
608    pub const_expr: Option<ConstExpr>,
609    pub parameter_list: Vec<Parameter>,
610    pub annotation_span: Option<(usize, usize)>,
611}
612
613#[derive(Debug, Clone)]
614pub enum Generic {
615    Type1 {
616        type_args1: Vec<Type>,
617        non_array_type: NonArrayType,
618        type_args2: Vec<Type>,
619    },
620    Type2 {
621        non_array_type: NonArrayType,
622        type_args: Vec<Type>,
623    },
624    Type3 {
625        type_args: Vec<Type>,
626    },
627}
628
629// fn generic_type_args_to_string(args: &[Type]) -> String {
630//     let mut args_str = String::new();
631
632//     args.iter().for_each(|t| {
633//         let mut cast = t.type_cast();
634//         cast.set_generic(true);
635
636//         args_str.push_str(", ");
637//         args_str.push_str(&cast.member_type());
638//     });
639
640//     args_str[2..].into()
641// }
642
643impl Generic {
644    pub fn to_value_type(&self) -> Result<ValueType, crate::error::AidlError> {
645        let generator = match self {
646            Generic::Type1 {
647                type_args1,
648                non_array_type: _,
649                type_args2: _,
650            } => type_generator::TypeGenerator::new_with_type(&type_args1[0])?,
651            Generic::Type2 {
652                non_array_type,
653                type_args: _,
654            } => type_generator::TypeGenerator::new(non_array_type)?,
655            Generic::Type3 { type_args } => {
656                type_generator::TypeGenerator::new_with_type(&type_args[0])?
657            }
658        };
659
660        Ok(generator.value_type)
661    }
662}
663
664#[derive(Debug, Default, Clone)]
665pub struct NonArrayType {
666    pub name: String,
667    pub generic: Option<Box<Generic>>,
668    pub name_span: Option<(usize, usize)>,
669}
670
671#[derive(Debug, Default, Clone)]
672pub struct ArrayType {
673    pub const_expr: Option<ConstExpr>,
674}
675
676#[derive(Debug, Default, Clone)]
677pub struct Type {
678    pub annotation_list: Vec<Annotation>,
679    pub non_array_type: NonArrayType,
680    pub array_types: Vec<ArrayType>,
681}
682
683impl Type {
684    pub fn to_generator(&self) -> Result<type_generator::TypeGenerator, crate::error::AidlError> {
685        type_generator::TypeGenerator::new_with_type(self)
686    }
687}
688
689#[derive(PartialEq)]
690pub enum AnnotationType {
691    IsNullable,
692    JavaOnly,
693    RustDerive,
694    VintfStability,
695}
696
697pub fn check_annotation_list(
698    annotation_list: &Vec<Annotation>,
699    query_type: AnnotationType,
700) -> (bool, String) {
701    for annotation in annotation_list {
702        match query_type {
703            AnnotationType::VintfStability if annotation.annotation == "@VintfStability" => {
704                return (true, "".to_owned())
705            }
706            AnnotationType::IsNullable if annotation.annotation == "@nullable" => {
707                return (true, "".to_owned())
708            }
709            AnnotationType::JavaOnly if annotation.annotation.starts_with("@JavaOnly") => {
710                return (true, "".to_owned())
711            }
712            AnnotationType::RustDerive if annotation.annotation == "@RustDerive" => {
713                let mut derives = Vec::new();
714
715                for param in &annotation.parameter_list {
716                    if param.const_expr.to_bool().unwrap_or(false) {
717                        derives.push(param.identifier.to_owned())
718                    }
719                }
720
721                return (true, derives.join(","));
722            }
723            _ => {}
724        }
725    }
726
727    (false, "".to_owned())
728}
729
730pub fn get_descriptor_from_annotation_list(annotation_list: &Vec<Annotation>) -> Option<String> {
731    for annotation in annotation_list {
732        if annotation.annotation == "@Descriptor" {
733            for param in &annotation.parameter_list {
734                if param.identifier == "value" {
735                    return Some(param.const_expr.to_value_string());
736                }
737            }
738        }
739    }
740
741    None
742}
743
744pub fn get_backing_type(
745    annotation_list: &Vec<Annotation>,
746    name_span: Option<(usize, usize)>,
747) -> Result<type_generator::TypeGenerator, crate::error::AidlError> {
748    // parse "@Backing(type="byte")"
749    for annotation in annotation_list {
750        if annotation.annotation == "@Backing" {
751            for param in &annotation.parameter_list {
752                if param.identifier == "type" {
753                    return type_generator::TypeGenerator::new(&NonArrayType {
754                        // The cstr is enclosed in quotes.
755                        name: param.const_expr.to_value_string().trim_matches('"').into(),
756                        generic: None,
757                        name_span,
758                    });
759                }
760            }
761        }
762    }
763
764    type_generator::TypeGenerator::new(&NonArrayType {
765        // The cstr is enclosed in quotes.
766        name: "byte".into(),
767        generic: None,
768        name_span: None,
769    })
770}
771
772fn parse_unary(mut pairs: pest::iterators::Pairs<Rule>) -> Result<ConstExpr, AidlError> {
773    let operator = pairs.next().unwrap().as_str().to_owned();
774    let factor = parse_factor(pairs.next().unwrap().into_inner().next().unwrap())?;
775    Ok(ConstExpr::new_unary(&operator, factor))
776}
777
778fn parse_intvalue(arg_value: &str, span: (usize, usize)) -> Result<ConstExpr, AidlError> {
779    let mut is_u8 = false;
780    let mut is_long = false;
781
782    let (value, radix) = if arg_value.starts_with("0x") || arg_value.starts_with("0X") {
783        (&arg_value[2..], 16)
784    } else {
785        (arg_value, 10)
786    };
787
788    let value = if value.ends_with('l') || value.ends_with('L') {
789        is_long = true;
790        &value[..value.len() - 1]
791    } else if let Some(stripped) = value.strip_suffix("u8") {
792        is_u8 = true;
793        stripped
794    } else {
795        value
796    };
797
798    if radix == 16 {
799        if is_u8 {
800            let parsed_value = u8::from_str_radix(value, radix).map_err(|err| {
801                make_parse_error(
802                    format!("invalid u8 hex literal '{arg_value}': {err}"),
803                    span.0,
804                    span.1,
805                )
806            })?;
807            Ok(ConstExpr::new(ValueType::Byte(parsed_value as _)))
808        } else if !is_long {
809            if let Ok(parsed_value) = u32::from_str_radix(value, radix) {
810                Ok(ConstExpr::new(ValueType::Int32(parsed_value as i32 as _)))
811            } else {
812                let parsed_value = u64::from_str_radix(value, radix).map_err(|err| {
813                    make_parse_error(
814                        format!("invalid hex literal '{arg_value}': {err}"),
815                        span.0,
816                        span.1,
817                    )
818                })?;
819                Ok(ConstExpr::new(ValueType::Int64(parsed_value as i64 as _)))
820            }
821        } else {
822            let parsed_value = u64::from_str_radix(value, radix).map_err(|err| {
823                make_parse_error(
824                    format!("invalid hex literal '{arg_value}': {err}"),
825                    span.0,
826                    span.1,
827                )
828            })?;
829            Ok(ConstExpr::new(ValueType::Int64(parsed_value as i64 as _)))
830        }
831    } else {
832        let parsed_value = i64::from_str_radix(value, radix).map_err(|err| {
833            make_parse_error(
834                format!("invalid integer literal '{arg_value}': {err}"),
835                span.0,
836                span.1,
837            )
838        })?;
839        if is_u8 {
840            if parsed_value > u8::MAX.into() || parsed_value < 0 {
841                return Err(make_parse_error(
842                    format!("u8 literal overflow: {parsed_value} is out of range (0..=255)"),
843                    span.0,
844                    span.1,
845                ));
846            }
847            Ok(ConstExpr::new(ValueType::Byte(parsed_value as i8 as _)))
848        } else if is_long {
849            Ok(ConstExpr::new(ValueType::Int64(parsed_value as _)))
850        } else if parsed_value <= i8::MAX.into() && parsed_value >= i8::MIN.into() {
851            Ok(ConstExpr::new(ValueType::Byte(parsed_value as i8 as _)))
852        } else if parsed_value <= i32::MAX.into() && parsed_value >= i32::MIN.into() {
853            Ok(ConstExpr::new(ValueType::Int32(parsed_value as i32 as _)))
854        } else {
855            Ok(ConstExpr::new(ValueType::Int64(parsed_value as _)))
856        }
857    }
858}
859
860fn parse_value(pair: pest::iterators::Pair<Rule>) -> Result<ConstExpr, AidlError> {
861    match pair.as_rule() {
862        Rule::qualified_name => Ok(ConstExpr::new(ValueType::Name(pair.as_str().into()))),
863        Rule::HEXVALUE | Rule::INTVALUE => {
864            let span = pair.as_span();
865            parse_intvalue(pair.as_str(), (span.start(), span.end()))
866        }
867        Rule::FLOATVALUE => {
868            let span = pair.as_span();
869            let value = pair.as_str();
870            let value = if let Some(stripped) = value.strip_suffix('f') {
871                stripped
872            } else {
873                value
874            };
875            let f = value.parse::<f64>().map_err(|_| {
876                make_parse_error(
877                    format!("invalid float literal: {}", pair.as_str()),
878                    span.start(),
879                    span.end(),
880                )
881            })?;
882            Ok(ConstExpr::new(ValueType::Double(f as _)))
883        }
884        Rule::TRUE_LITERAL => Ok(ConstExpr::new(ValueType::Bool(true))),
885        Rule::FALSE_LITERAL => Ok(ConstExpr::new(ValueType::Bool(false))),
886        _ => unreachable!("Unexpected rule in parse_value(): {}", pair),
887    }
888}
889
890fn parse_factor(pair: pest::iterators::Pair<Rule>) -> Result<ConstExpr, AidlError> {
891    // println!("parse_factor {:?}", pair);
892    match pair.as_rule() {
893        Rule::expression => parse_expression(pair.clone().into_inner()),
894        Rule::unary => parse_unary(pair.into_inner()),
895        Rule::value => parse_value(pair.into_inner().next().unwrap()),
896        _ => unreachable!("Unexpected rule in parse_factor(): {}", pair),
897    }
898}
899
900fn parse_expression_term(pair: pest::iterators::Pair<Rule>) -> Result<ConstExpr, AidlError> {
901    match pair.as_rule() {
902        Rule::equality
903        | Rule::comparison
904        | Rule::bitwise_or
905        | Rule::bitwise_xor
906        | Rule::bitwise_and
907        | Rule::shift
908        | Rule::arith
909        | Rule::logical_or
910        | Rule::logical_and => parse_expression(pair.clone().into_inner()),
911        Rule::factor => parse_factor(pair.into_inner().next().unwrap()),
912        _ => unreachable!("Unexpected rule in Rule::parse_expression_into: {}", pair),
913    }
914}
915
916fn parse_expression(mut pairs: pest::iterators::Pairs<Rule>) -> Result<ConstExpr, AidlError> {
917    let mut lhs = parse_expression_term(pairs.next().unwrap())?;
918
919    while let Some(pair) = pairs.next() {
920        let op = pair.as_str().to_owned();
921        let rhs = parse_expression_term(pairs.next().unwrap())?;
922
923        lhs = ConstExpr::new_expr(lhs, &op, rhs)
924    }
925
926    Ok(lhs)
927}
928
929fn parse_string_term(pair: pest::iterators::Pair<Rule>) -> ConstExpr {
930    match pair.as_rule() {
931        Rule::C_STR => {
932            let string = pair.as_str();
933            ConstExpr::new(ValueType::String(string[1..string.len() - 1].into()))
934        }
935        Rule::qualified_name => ConstExpr::new(ValueType::Name(pair.as_str().into())),
936        _ => unreachable!("Unexpected rule in Rule::parse_string_term: {}", pair),
937    }
938}
939
940fn parse_string_expr(pairs: pest::iterators::Pairs<Rule>) -> Result<ConstExpr, AidlError> {
941    let mut expr: Option<ConstExpr> = None;
942
943    for pair in pairs {
944        match pair.as_rule() {
945            Rule::string_term => {
946                let term = parse_string_term(pair.into_inner().next().unwrap());
947                expr = match expr {
948                    Some(expr) => Some(ConstExpr::new_expr(expr, "+", term)),
949                    None => Some(term),
950                }
951            }
952            _ => unreachable!("Unexpected rule in Rule::parse_string_expr: {}", pair),
953        }
954    }
955
956    Ok(expr.expect("internal: empty string_expr"))
957}
958
959fn parse_const_expr(pair: pest::iterators::Pair<Rule>) -> Result<ConstExpr, AidlError> {
960    match pair.as_rule() {
961        Rule::constant_value_list => {
962            let mut value_list = Vec::new();
963            for pair in pair.into_inner() {
964                match pair.as_rule() {
965                    Rule::const_expr => {
966                        value_list.push(parse_const_expr(pair.into_inner().next().unwrap())?);
967                    }
968                    _ => unreachable!("Unexpected rule in Rule::constant_value_list: {}", pair),
969                }
970            }
971            Ok(ConstExpr::new(ValueType::Array(value_list)))
972        }
973
974        Rule::CHARVALUE => {
975            let mut found = false;
976            let mut has_backslash = false;
977            for ch in pair.as_str().chars() {
978                if !found && ch == '\'' {
979                    found = true;
980                } else if found {
981                    if !has_backslash && ch == '\\' {
982                        has_backslash = true;
983                    } else {
984                        return Ok(ConstExpr::new(ValueType::Char(ch)));
985                    }
986                }
987            }
988            unreachable!()
989        }
990
991        Rule::expression => parse_expression(pair.clone().into_inner()),
992
993        Rule::string_expr => parse_string_expr(pair.into_inner()),
994
995        _ => unreachable!("Unexpected rule in parse_const_expr(): {}", pair),
996    }
997}
998
999fn parse_parameter(pairs: pest::iterators::Pairs<Rule>) -> Result<Parameter, AidlError> {
1000    let mut parameter = Parameter {
1001        identifier: "".to_string(),
1002        const_expr: ConstExpr::default(),
1003    };
1004
1005    for pair in pairs {
1006        match pair.as_rule() {
1007            Rule::identifier => {
1008                parameter.identifier = pair.as_str().into();
1009            }
1010            Rule::const_expr => {
1011                parameter.const_expr = parse_const_expr(pair.into_inner().next().unwrap())?;
1012            }
1013            _ => unreachable!("Unexpected rule in parse_parameter(): {}", pair),
1014        }
1015    }
1016
1017    Ok(parameter)
1018}
1019
1020fn parse_parameter_list(pairs: pest::iterators::Pairs<Rule>) -> Result<Vec<Parameter>, AidlError> {
1021    let mut list = Vec::new();
1022    for pair in pairs {
1023        list.push(parse_parameter(pair.into_inner())?);
1024    }
1025
1026    Ok(list)
1027}
1028
1029fn parse_annotation(pairs: pest::iterators::Pairs<Rule>) -> Result<Annotation, AidlError> {
1030    let mut annotation = Annotation::default();
1031    for pair in pairs {
1032        match pair.as_rule() {
1033            Rule::ANNOTATION => {
1034                let span = pair.as_span();
1035                annotation.annotation = pair.as_str().into();
1036                annotation.annotation_span = Some((span.start(), span.end()));
1037            }
1038
1039            Rule::const_expr => {
1040                annotation.const_expr = Some(parse_const_expr(pair.into_inner().next().unwrap())?);
1041            }
1042
1043            Rule::parameter_list => {
1044                annotation.parameter_list = parse_parameter_list(pair.into_inner())?;
1045            }
1046
1047            _ => unreachable!("Unexpected rule in parse_annotation(): {}", pair),
1048        }
1049    }
1050
1051    Ok(annotation)
1052}
1053
1054fn parse_annotation_list(
1055    pairs: pest::iterators::Pairs<Rule>,
1056) -> Result<Vec<Annotation>, AidlError> {
1057    let mut annotation_list = Vec::new();
1058    for pair in pairs {
1059        annotation_list.push(parse_annotation(pair.into_inner())?);
1060    }
1061
1062    Ok(annotation_list)
1063}
1064
1065fn parse_type_args(pairs: pest::iterators::Pairs<Rule>) -> Result<Vec<Type>, AidlError> {
1066    let mut res = Vec::new();
1067
1068    for pair in pairs {
1069        match pair.as_rule() {
1070            Rule::r#type => res.push(parse_type(pair.into_inner())?),
1071            _ => unreachable!("Unexpected rule in parse_type_args(): {}", pair),
1072        }
1073    }
1074
1075    Ok(res)
1076}
1077
1078fn parse_non_array_type(pairs: pest::iterators::Pairs<Rule>) -> Result<NonArrayType, AidlError> {
1079    let mut non_array_type = NonArrayType::default();
1080
1081    for pair in pairs {
1082        match pair.as_rule() {
1083            Rule::qualified_name => {
1084                let span = pair.as_span();
1085                non_array_type.name = pair.as_str().into();
1086                non_array_type.name_span = Some((span.start(), span.end()));
1087            }
1088            Rule::generic_type1 => {
1089                let mut pairs = pair.into_inner();
1090                let generic = Generic::Type1 {
1091                    type_args1: parse_type_args(pairs.next().unwrap().into_inner())?,
1092                    non_array_type: parse_non_array_type(pairs.next().unwrap().into_inner())?,
1093                    type_args2: parse_type_args(pairs.next().unwrap().into_inner())?,
1094                };
1095
1096                non_array_type.generic = Some(Box::new(generic));
1097            }
1098
1099            Rule::generic_type2 => {
1100                let mut pairs = pair.into_inner();
1101                let generic = Generic::Type2 {
1102                    non_array_type: parse_non_array_type(pairs.next().unwrap().into_inner())?,
1103                    type_args: parse_type_args(pairs.next().unwrap().into_inner())?,
1104                };
1105
1106                non_array_type.generic = Some(Box::new(generic));
1107            }
1108            Rule::generic_type3 => {
1109                let mut pairs = pair.into_inner();
1110                let generic = Generic::Type3 {
1111                    type_args: parse_type_args(pairs.next().unwrap().into_inner())?,
1112                };
1113
1114                non_array_type.generic = Some(Box::new(generic));
1115            }
1116            _ => {
1117                unreachable!();
1118            }
1119        }
1120    }
1121
1122    Ok(non_array_type)
1123}
1124
1125fn parse_array_type(pairs: pest::iterators::Pairs<Rule>) -> Result<ArrayType, AidlError> {
1126    let mut array_type = ArrayType::default();
1127
1128    for pair in pairs {
1129        match pair.as_rule() {
1130            Rule::const_expr => {
1131                array_type.const_expr = Some(parse_const_expr(pair.into_inner().next().unwrap())?);
1132            }
1133            _ => unreachable!("Unexpected rule in parse_array_type(): {}", pair),
1134        }
1135    }
1136
1137    Ok(array_type)
1138}
1139
1140fn parse_type(pairs: pest::iterators::Pairs<Rule>) -> Result<Type, AidlError> {
1141    let mut r#type = Type::default();
1142
1143    for pair in pairs {
1144        match pair.as_rule() {
1145            Rule::annotation_list => {
1146                r#type.annotation_list = parse_annotation_list(pair.into_inner())?;
1147            }
1148            Rule::non_array_type => {
1149                r#type.non_array_type = parse_non_array_type(pair.into_inner())?;
1150            }
1151            Rule::array_type => {
1152                r#type
1153                    .array_types
1154                    .push(parse_array_type(pair.into_inner())?);
1155            }
1156            _ => {
1157                unreachable!("Unexpected rule in parse_type(): {}", pair);
1158            }
1159        }
1160    }
1161
1162    Ok(r#type)
1163}
1164
1165fn parse_variable_decl(
1166    pairs: pest::iterators::Pairs<Rule>,
1167    constant: bool,
1168) -> Result<VariableDecl, AidlError> {
1169    let mut decl = VariableDecl {
1170        constant,
1171        ..Default::default()
1172    };
1173
1174    for pair in pairs {
1175        match pair.as_rule() {
1176            Rule::annotation_list => {
1177                decl.annotation_list = parse_annotation_list(pair.into_inner())?;
1178            }
1179            Rule::r#type => {
1180                decl.r#type = parse_type(pair.into_inner())?;
1181            }
1182            Rule::identifier => {
1183                decl.identifier = pair.as_str().into();
1184            }
1185            Rule::const_expr => match pair.into_inner().next() {
1186                Some(pair) => decl.const_expr = Some(parse_const_expr(pair)?),
1187                None => decl.const_expr = None,
1188            },
1189            _ => unreachable!(
1190                "Unexpected rule in parse_variable_decl(): {}\t{}",
1191                pair,
1192                pair.as_str()
1193            ),
1194        }
1195    }
1196
1197    Ok(decl)
1198}
1199
1200fn parse_arg(pairs: pest::iterators::Pairs<Rule>) -> Result<Arg, AidlError> {
1201    let mut arg = Arg::default();
1202
1203    for pair in pairs {
1204        match pair.as_rule() {
1205            Rule::direction => {
1206                let span = pair.as_span();
1207                arg.direction = match pair.as_str() {
1208                    "in" => Direction::In,
1209                    "out" => Direction::Out,
1210                    "inout" => Direction::Inout,
1211                    _ => {
1212                        return Err(make_parse_error(
1213                            format!("unsupported direction: {}", pair.as_str()),
1214                            span.start(),
1215                            span.end(),
1216                        ));
1217                    }
1218                };
1219                arg.direction_span = Some((span.start(), span.end()));
1220            }
1221            Rule::r#type => {
1222                arg.r#type = parse_type(pair.into_inner())?;
1223            }
1224            Rule::identifier => {
1225                arg.identifier = pair.as_str().into();
1226            }
1227            _ => unreachable!("Unexpected rule in parse_arg(): {}", pair),
1228        }
1229    }
1230
1231    Ok(arg)
1232}
1233
1234fn parse_method_decl(pairs: pest::iterators::Pairs<Rule>) -> Result<MethodDecl, AidlError> {
1235    let mut decl = MethodDecl::default();
1236
1237    for pair in pairs {
1238        match pair.as_rule() {
1239            Rule::annotation_list => {
1240                decl.annotation_list = parse_annotation_list(pair.into_inner())?;
1241            }
1242            Rule::ONEWAY => {
1243                decl.oneway = true;
1244            }
1245            Rule::r#type => {
1246                decl.r#type = parse_type(pair.into_inner())?;
1247            }
1248            Rule::identifier => {
1249                let span = pair.as_span();
1250                decl.identifier = pair.as_str().into();
1251                decl.identifier_span = Some((span.start(), span.end()));
1252            }
1253            Rule::arg_list => {
1254                for pair in pair.into_inner() {
1255                    match pair.as_rule() {
1256                        Rule::arg => {
1257                            decl.arg_list.push(parse_arg(pair.into_inner())?);
1258                        }
1259                        _ => unreachable!(
1260                            "Unexpected rule in parse_method_decl(): {}, \"{}\"",
1261                            pair,
1262                            pair.as_str()
1263                        ),
1264                    }
1265                }
1266            }
1267            Rule::INTVALUE => {
1268                let span = pair.as_span();
1269                let expr = parse_intvalue(pair.as_str(), (span.start(), span.end()))?
1270                    .calculate()
1271                    .map_err(|e| make_parse_error(e.message, span.start(), span.end()))?;
1272                decl.intvalue = Some(match expr.value {
1273                    ValueType::Byte(v) => v as _,
1274                    ValueType::Int32(v) => v as _,
1275                    ValueType::Int64(v) => v,
1276                    _ => unreachable!(
1277                        "Unexpected Expression in parse_method_decl(): {}, \"{}\"",
1278                        pair,
1279                        pair.as_str()
1280                    ),
1281                });
1282                decl.intvalue_span = Some((span.start(), span.end()));
1283            }
1284            _ => unreachable!(
1285                "Unexpected rule in parse_method_decl(): {}, \"{}\"",
1286                pair,
1287                pair.as_str()
1288            ),
1289        }
1290    }
1291
1292    Ok(decl)
1293}
1294
1295fn parse_interface_members(
1296    pairs: pest::iterators::Pairs<Rule>,
1297    interface: &mut InterfaceDecl,
1298) -> Result<(), AidlError> {
1299    for pair in pairs {
1300        match pair.as_rule() {
1301            Rule::method_decl => {
1302                interface
1303                    .method_list
1304                    .push(parse_method_decl(pair.into_inner())?);
1305            }
1306
1307            Rule::constant_decl => {
1308                interface
1309                    .constant_list
1310                    .push(parse_variable_decl(pair.into_inner(), true)?);
1311            }
1312
1313            Rule::interface_members => {
1314                parse_interface_members(pair.into_inner(), interface)?;
1315            }
1316
1317            Rule::decl => {
1318                interface
1319                    .members
1320                    .append(&mut parse_decl(pair.into_inner())?);
1321            }
1322
1323            _ => unreachable!("Unexpected rule in parse_interface_members(): {}", pair),
1324        }
1325    }
1326    Ok(())
1327}
1328
1329fn parse_interface_decl(
1330    annotation_list: Vec<Annotation>,
1331    pairs: pest::iterators::Pairs<Rule>,
1332) -> Result<Declaration, AidlError> {
1333    let mut interface = InterfaceDecl {
1334        annotation_list,
1335        ..Default::default()
1336    };
1337
1338    for pair in pairs {
1339        match pair.as_rule() {
1340            Rule::ONEWAY => {
1341                interface.oneway = true;
1342            }
1343
1344            Rule::qualified_name => {
1345                let span = pair.as_span();
1346                interface.name = pair.as_str().into();
1347                interface.name_span = Some((span.start(), span.end()));
1348            }
1349
1350            Rule::interface_members => {
1351                parse_interface_members(pair.into_inner(), &mut interface)?;
1352            }
1353
1354            _ => unreachable!("Unexpected rule in parse_interface_decl(): {}", pair),
1355        }
1356    }
1357
1358    Ok(Declaration::Interface(interface))
1359}
1360
1361fn parse_parcelable_members(
1362    pairs: pest::iterators::Pairs<Rule>,
1363) -> Result<Vec<Declaration>, AidlError> {
1364    let mut res = Vec::new();
1365
1366    for pair in pairs {
1367        match pair.as_rule() {
1368            Rule::variable_decl => {
1369                res.push(Declaration::Variable(parse_variable_decl(
1370                    pair.into_inner(),
1371                    false,
1372                )?));
1373            }
1374            Rule::constant_decl => {
1375                res.push(Declaration::Variable(parse_variable_decl(
1376                    pair.into_inner(),
1377                    true,
1378                )?));
1379            }
1380            Rule::decl => res.append(&mut parse_decl(pair.into_inner())?),
1381            _ => unreachable!("Unexpected rule in parse_parcelable_members(): {}", pair),
1382        }
1383    }
1384
1385    Ok(res)
1386}
1387
1388fn parse_optional_type_params(pairs: pest::iterators::Pairs<Rule>) -> Vec<String> {
1389    let mut res = Vec::new();
1390
1391    for pair in pairs {
1392        match pair.as_rule() {
1393            Rule::identifier => res.push(pair.as_str().into()),
1394            _ => unreachable!("Unexpected rule in parse_optional_type_params(): {}", pair),
1395        }
1396    }
1397
1398    res
1399}
1400
1401fn parse_unstructured_parcelable(
1402    parcelable: &mut ParcelableDecl,
1403    mut pairs: pest::iterators::Pairs<Rule>,
1404) -> Result<(), AidlError> {
1405    enum HeaderType {
1406        CppHeader,
1407        NdkHeader,
1408        RustType,
1409    }
1410
1411    let (first, second) = pairs
1412        .next()
1413        .zip(pairs.next())
1414        .expect("Incomplete rule in parse_unstructured_parcelable()");
1415
1416    let header = match first.as_rule() {
1417        Rule::CPP_HEADER => HeaderType::CppHeader,
1418        Rule::NDK_HEADER => HeaderType::NdkHeader,
1419        Rule::RUST_TYPE => HeaderType::RustType,
1420        _ => unreachable!(
1421            "Unexpected rule in parse_unstructured_parcelable(): {}",
1422            first
1423        ),
1424    };
1425
1426    match second.as_rule() {
1427        Rule::C_STR => {
1428            let str = second.as_str();
1429            let str = str[1..str.len() - 1].into();
1430            match header {
1431                HeaderType::CppHeader => parcelable.cpp_header = str,
1432                HeaderType::NdkHeader => parcelable.ndk_header = str,
1433                HeaderType::RustType => parcelable.rust_type = str,
1434            }
1435        }
1436        _ => unreachable!(
1437            "Unexpected rule in parse_unstructured_parcelable(): {}",
1438            second
1439        ),
1440    }
1441
1442    Ok(())
1443}
1444
1445fn parse_parcelable_decl(
1446    annotation_list: Vec<Annotation>,
1447    pairs: pest::iterators::Pairs<Rule>,
1448) -> Result<Declaration, AidlError> {
1449    let mut parcelable = ParcelableDecl {
1450        annotation_list,
1451        ..Default::default()
1452    };
1453
1454    for pair in pairs {
1455        match pair.as_rule() {
1456            Rule::qualified_name => {
1457                parcelable.name = pair.as_str().into();
1458            }
1459
1460            Rule::optional_type_params => {
1461                parcelable.type_params = parse_optional_type_params(pair.into_inner());
1462            }
1463
1464            Rule::parcelable_members => {
1465                parcelable
1466                    .members
1467                    .append(&mut parse_parcelable_members(pair.into_inner())?);
1468            }
1469
1470            Rule::optional_unstructured_headers => {
1471                parse_unstructured_parcelable(&mut parcelable, pair.into_inner())?;
1472            }
1473
1474            _ => unreachable!("Unexpected rule in parse_parcelable_decl(): {}", pair),
1475        }
1476    }
1477
1478    Ok(Declaration::Parcelable(parcelable))
1479}
1480
1481#[derive(Debug, Default, Clone)]
1482pub struct Enumerator {
1483    pub identifier: String,
1484    pub const_expr: Option<ConstExpr>,
1485}
1486
1487#[derive(Debug, Default, Clone)]
1488pub struct EnumDecl {
1489    pub namespace: Namespace,
1490    pub annotation_list: Vec<Annotation>,
1491    pub name: String,
1492    pub name_span: Option<(usize, usize)>,
1493    pub enumerator_list: Vec<Enumerator>,
1494    pub members: Vec<Declaration>,
1495}
1496
1497fn parse_enumerator(pairs: pest::iterators::Pairs<Rule>) -> Result<Enumerator, AidlError> {
1498    let mut res = Enumerator::default();
1499
1500    for pair in pairs {
1501        match pair.as_rule() {
1502            Rule::identifier => {
1503                res.identifier = pair.as_str().into();
1504            }
1505            Rule::const_expr => {
1506                res.const_expr = Some(parse_const_expr(pair.into_inner().next().unwrap())?);
1507            }
1508            _ => unreachable!("Unexpected rule in parse_enumerator(): {}", pair),
1509        }
1510    }
1511
1512    Ok(res)
1513}
1514
1515fn parse_enum_decl(
1516    annotation_list: Vec<Annotation>,
1517    pairs: pest::iterators::Pairs<Rule>,
1518) -> Result<Declaration, AidlError> {
1519    let mut enum_decl = EnumDecl {
1520        annotation_list: annotation_list.clone(),
1521        ..Default::default()
1522    };
1523
1524    for pair in pairs {
1525        match pair.as_rule() {
1526            Rule::qualified_name => {
1527                let span = pair.as_span();
1528                enum_decl.name = pair.as_str().into();
1529                enum_decl.name_span = Some((span.start(), span.end()));
1530            }
1531            Rule::enumerator => enum_decl
1532                .enumerator_list
1533                .push(parse_enumerator(pair.into_inner())?),
1534            _ => unreachable!("Unexpected rule in parse_enum_decl(): {}", pair),
1535        }
1536    }
1537
1538    Ok(Declaration::Enum(enum_decl))
1539}
1540
1541#[derive(Debug, Default, Clone)]
1542pub struct UnionDecl {
1543    pub namespace: Namespace,
1544    pub annotation_list: Vec<Annotation>,
1545    pub name: String,
1546    pub name_span: Option<(usize, usize)>,
1547    pub type_params: Vec<String>,
1548    pub members: Vec<Declaration>,
1549}
1550
1551fn parse_union_decl(
1552    annotation_list: Vec<Annotation>,
1553    pairs: pest::iterators::Pairs<Rule>,
1554) -> Result<Declaration, AidlError> {
1555    let mut union_decl = UnionDecl {
1556        annotation_list,
1557        ..Default::default()
1558    };
1559
1560    for pair in pairs {
1561        match pair.as_rule() {
1562            Rule::qualified_name => {
1563                let span = pair.as_span();
1564                union_decl.name = pair.as_str().into();
1565                union_decl.name_span = Some((span.start(), span.end()));
1566            }
1567            Rule::optional_type_params => {
1568                union_decl.type_params = parse_optional_type_params(pair.into_inner());
1569            }
1570            Rule::parcelable_members => {
1571                union_decl.members = parse_parcelable_members(pair.into_inner())?;
1572            }
1573            _ => unreachable!("Unexpected rule in parse_union_decl(): {}", pair),
1574        }
1575    }
1576    Ok(Declaration::Union(union_decl))
1577}
1578
1579fn parse_decl(pairs: pest::iterators::Pairs<Rule>) -> Result<Vec<Declaration>, AidlError> {
1580    let mut annotation_list = Vec::new();
1581    let mut declarations = Vec::new();
1582
1583    for pair in pairs {
1584        match pair.as_rule() {
1585            Rule::annotation_list => {
1586                annotation_list = parse_annotation_list(pair.into_inner())?;
1587            }
1588            Rule::interface_decl => {
1589                declarations.push(parse_interface_decl(
1590                    annotation_list.clone(),
1591                    pair.into_inner(),
1592                )?);
1593            }
1594
1595            Rule::parcelable_decl => {
1596                declarations.push(parse_parcelable_decl(
1597                    annotation_list.clone(),
1598                    pair.into_inner(),
1599                )?);
1600            }
1601            Rule::enum_decl => {
1602                declarations.push(parse_enum_decl(annotation_list.clone(), pair.into_inner())?);
1603            }
1604            Rule::union_decl => {
1605                declarations.push(parse_union_decl(
1606                    annotation_list.clone(),
1607                    pair.into_inner(),
1608                )?);
1609            }
1610
1611            _ => unreachable!("Unexpected rule in parse_decl(): {}", pair),
1612        };
1613    }
1614
1615    Ok(declarations)
1616}
1617
1618pub fn calculate_namespace(decl: &mut Declaration, mut namespace: Namespace) {
1619    if decl.is_variable().is_some() {
1620        return;
1621    }
1622
1623    namespace.push(decl.name());
1624
1625    decl.set_namespace(namespace.clone());
1626
1627    DECLARATION_MAP.with(|hashmap| {
1628        hashmap.borrow_mut().insert(namespace.clone(), decl.clone());
1629    });
1630
1631    for decl in decl.members_mut() {
1632        calculate_namespace(decl, namespace.clone());
1633    }
1634}
1635
1636pub fn parse_document(ctx: &SourceContext) -> Result<Document, AidlError> {
1637    let _guard = SourceGuard::new(&ctx.filename, &ctx.source);
1638    let mut document = Document::new();
1639
1640    match AIDLParser::parse(Rule::document, &ctx.source) {
1641        Ok(pairs) => {
1642            for pair in pairs {
1643                match pair.as_rule() {
1644                    Rule::package => {
1645                        document.package = Some(pair.into_inner().next().unwrap().as_str().into());
1646                    }
1647
1648                    Rule::imports => {
1649                        for pair in pair.into_inner() {
1650                            let import = pair.as_str().to_string();
1651                            let key = match import.rfind('.') {
1652                                Some(idx) => &import[(idx + 1)..],
1653                                None => &import,
1654                            };
1655                            document.imports.insert(key.into(), import);
1656                        }
1657                    }
1658
1659                    Rule::decl => {
1660                        document.decls.append(&mut parse_decl(pair.into_inner())?);
1661                    }
1662
1663                    Rule::EOI => {}
1664
1665                    _ => {
1666                        unreachable!("Unexpected rule in parse_document(): {}", pair)
1667                    }
1668                }
1669            }
1670
1671            // println!("{:?}", document);
1672        }
1673        Err(err) => {
1674            return Err(pest_error_to_diagnostic(err, &ctx.filename, &ctx.source).into());
1675        }
1676    }
1677
1678    let namespace = if let Some(ref package) = document.package {
1679        Namespace::new(package, Namespace::AIDL)
1680    } else {
1681        Namespace::default()
1682    };
1683
1684    for decl in &mut document.decls {
1685        calculate_namespace(decl, namespace.clone());
1686    }
1687
1688    Ok(document)
1689}
1690
1691pub fn reset() {
1692    DECLARATION_MAP.with(|hashmap| {
1693        hashmap.borrow_mut().clear();
1694    });
1695    NAMESPACE_STACK.with(|stack| {
1696        stack.borrow_mut().clear();
1697    });
1698    DOCUMENT.with(|doc| {
1699        *doc.borrow_mut() = Document::new();
1700    });
1701    SYMBOL_TABLE.with(|table| {
1702        table.borrow_mut().clear();
1703    });
1704}
1705
1706#[cfg(test)]
1707mod tests {
1708    use super::*;
1709    use std::error::Error;
1710
1711    #[test]
1712    fn test_parse_string_expr() -> Result<(), Box<dyn Error>> {
1713        let mut res =
1714            AIDLParser::parse(Rule::string_expr, r##""Hello" + " World""##).map_err(|err| {
1715                println!("{err}");
1716                err
1717            })?;
1718
1719        let expr = parse_string_expr(res.next().unwrap().into_inner())?;
1720        assert_eq!(
1721            expr,
1722            ConstExpr::new_expr(
1723                ConstExpr::new(ValueType::String("Hello".into())),
1724                "+",
1725                ConstExpr::new(ValueType::String(" World".into()))
1726            )
1727        );
1728
1729        Ok(())
1730    }
1731
1732    #[test]
1733    fn test_parse_expression() -> Result<(), Box<dyn Error>> {
1734        let mut res =
1735            AIDLParser::parse(Rule::expression, r##"1 + -3 * 2 << 2 | 4"##).map_err(|err| {
1736                println!("{err}");
1737                err
1738            })?;
1739
1740        let expr = parse_expression(res.next().unwrap().into_inner())?;
1741        // assert_eq!(
1742        //     expr.clone(),
1743        //     // Expression::Expr {
1744        //     //     as_str: "1 + -3 * 2 << 2 | 4".into(),
1745        //     //     lhs: Box::new(Expression::Expr {
1746        //     //         as_str: "1 + -3 * 2 << 2 | 4".into(),
1747        //     //         lhs: Box::new(Expression::Expr {
1748        //     //             as_str: "1 + -3 * 2 << 2 | 4".into(),
1749        //     //             lhs: Box::new(Expression::Int8(1)),
1750        //     //             operator: "+".to_string(),
1751        //     //             rhs: Box::new(Expression::Expr {
1752        //     //                 as_str: "1 + -3 * 2 << 2 | 4".into(),
1753        //     //                 lhs: Box::new(Expression::Unary {
1754        //     //                     operator: "-".to_string(),
1755        //     //                     expr: Box::new(Expression::Int8(3))
1756        //     //                 }),
1757        //     //                 operator: "*".to_string(),
1758        //     //                 rhs: Box::new(Expression::Int8(2))
1759        //     //             })
1760        //     //         }),
1761        //     //         operator: "<<".to_string(),
1762        //     //         rhs: Box::new(Expression::Int8(2))
1763        //     //     }),
1764        //     //     operator: "|".to_string(),
1765        //     //     rhs: Box::new(Expression::Int8(4))
1766        //     // },
1767        //     ConstExpr::default(),
1768        // );
1769
1770        assert_eq!(
1771            expr.calculate().unwrap(),
1772            ConstExpr::new(ValueType::Int64(-20))
1773        );
1774
1775        Ok(())
1776    }
1777
1778    #[test]
1779    fn test_namespace_guard() {
1780        let _ns_1 = NamespaceGuard::new(&Namespace::new("1.1", Namespace::AIDL));
1781        {
1782            assert_eq!(current_namespace(), Namespace::new("1.1", Namespace::AIDL));
1783            let _ns_2 = NamespaceGuard::new(&Namespace::new("2.2", Namespace::AIDL));
1784            {
1785                assert_eq!(current_namespace(), Namespace::new("2.2", Namespace::AIDL));
1786                let _ns_3 = NamespaceGuard::new(&Namespace::new("3.3", Namespace::AIDL));
1787                assert_eq!(current_namespace(), Namespace::new("3.3", Namespace::AIDL));
1788            }
1789            assert_eq!(current_namespace(), Namespace::new("2.2", Namespace::AIDL));
1790        }
1791    }
1792
1793    // 1.1n: thread-local state is cleared after SourceGuard is dropped
1794    #[test]
1795    fn test_source_guard_cleanup_on_drop() {
1796        {
1797            let _guard = SourceGuard::new("test.aidl", "source text");
1798            assert_eq!(current_source_name(), "test.aidl");
1799            assert_eq!(current_source_text(), "source text");
1800        }
1801        // After drop, thread-locals should be cleared
1802        assert_eq!(current_source_name(), "");
1803        assert_eq!(current_source_text(), "");
1804    }
1805
1806    // 1.1o: thread-local state is cleared even when a panic occurs inside SourceGuard
1807    #[test]
1808    fn test_source_guard_cleanup_on_panic() {
1809        let result = std::panic::catch_unwind(|| {
1810            let _guard = SourceGuard::new("panic.aidl", "panic source");
1811            panic!("intentional panic to test cleanup");
1812        });
1813        assert!(result.is_err());
1814        assert_eq!(current_source_name(), "");
1815        assert_eq!(current_source_text(), "");
1816    }
1817}