mapfile_parser/
symbol_decomp_state.rs

1/* SPDX-FileCopyrightText: © 2025 Decompollaborate */
2/* SPDX-License-Identifier: MIT */
3
4use std::path::PathBuf;
5
6use crate::{section, symbol};
7
8pub enum SymbolDecompState<'sect> {
9    /// The symbol has been decompiled.
10    /// In other words it is being handled by a compiler instead of assembled from automatic disassemblies.
11    Decomped(&'sect symbol::Symbol),
12    /// The symbol haven't been decompiled yet.
13    /// This was built from an automatic disassembly.
14    Undecomped(&'sect symbol::Symbol),
15}
16
17pub struct SymbolDecompStateIter<'sect> {
18    section: &'sect section::Section,
19    whole_file_is_undecomped: bool,
20    functions_path: Option<PathBuf>,
21
22    index: usize,
23}
24
25impl<'sect> SymbolDecompStateIter<'sect> {
26    pub(crate) fn new(
27        section: &'sect section::Section,
28        whole_file_is_undecomped: bool,
29        functions_path: Option<PathBuf>,
30    ) -> Self {
31        Self {
32            section,
33            whole_file_is_undecomped,
34            functions_path,
35
36            index: 0,
37        }
38    }
39}
40
41impl<'sect> Iterator for SymbolDecompStateIter<'sect> {
42    type Item = SymbolDecompState<'sect>;
43
44    fn next(&mut self) -> Option<Self::Item> {
45        // Skip over `.NON_MATCHING` symbols
46        while self.index < self.section.symbols.len() {
47            let sym = &self.section.symbols[self.index];
48            if !sym.name.ends_with(".NON_MATCHING") {
49                break;
50            }
51            self.index += 1;
52        }
53        if self.index >= self.section.symbols.len() {
54            return None;
55        }
56
57        let sym = &self.section.symbols[self.index];
58        self.index += 1;
59
60        if sym.inferred_static {
61            return Some(SymbolDecompState::Decomped(sym));
62        } else if self.whole_file_is_undecomped || sym.nonmatching_sym_exists {
63            return Some(SymbolDecompState::Undecomped(sym));
64        } else if let Some(functions_path) = &self.functions_path {
65            if functions_path.join(sym.name.clone() + ".s").exists() {
66                return Some(SymbolDecompState::Undecomped(sym));
67            }
68        }
69
70        Some(SymbolDecompState::Decomped(sym))
71    }
72}