Seperate this into more files and add way more features ( NOT ARCHITECTURES ) like RTTI analysis. Syntax highlighting for disassembly view, much more performant string view, more advanced everything

use arch::x86::ArchSyntax;
use capstone::{prelude::*, Capstone};
use eframe::{
    egui::{
        self, menu, style::*, Align2, Color32, Context, FontData, FontDefinitions, FontFamily, FontId, Grid, Layout, RichText, Rounding, ScrollArea, SidePanel, Stroke, Style, TextStyle, TopBottomPanel, Ui, Vec2
    },
    emath::Align,
    App, CreationContext, Frame, NativeOptions,
};
use object::{Object, ObjectSection, SectionKind};
use rfd::FileDialog;
use std::{
    borrow::Cow,
    collections::HashMap,
    fs::File,
    io::Read,
    str,
    sync::Arc,
};

mod symbol;
use symbol::{extract_symbols, SymbolInfo};

fn main() {
    let app = BinaryAnalyzerApp::default();
    let native_options = NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([1280.0, 800.0]),
        ..Default::default()
    };
    eframe::run_native(
        "Rust Binary Analyzer",
        native_options,
        Box::new(|cc| Ok(Box::new(app.setup(cc)))),
    )
    .expect("Failed to start eframe");
}

struct BinaryAnalyzerApp {
    binary_path: String,
    analysis_result: AnalysisResult,
    error_message: Option<String>,
    selected_section: Option<SectionInfo>,
    selected_symbol: Option<SymbolInfo>,
    selected_string: Option<StringInfo>,
    dark_mode: bool,
    recent_files: Vec<String>,
    disassembly_cache: HashMap<u64, String>,
    search_query: String,
    selected_tab: Tab,
    navigation_view: NavigationView,
    log_messages: Vec<String>,
    settings_open: bool,
}

impl Default for BinaryAnalyzerApp {
    fn default() -> Self {
        Self {
            binary_path: String::new(),
            analysis_result: AnalysisResult::default(),
            error_message: None,
            selected_section: None,
            selected_symbol: None,
            selected_string: None,
            dark_mode: true,
            recent_files: Vec::new(),
            disassembly_cache: HashMap::new(),
            search_query: String::new(),
            selected_tab: Tab::SectionDetails,
            navigation_view: NavigationView::Sections,
            log_messages: Vec::new(),
            settings_open: false,
        }
    }
}

impl BinaryAnalyzerApp {
    fn setup(self, cc: &CreationContext) -> Self {
        self.configure_fonts(cc);
        self.configure_visuals(cc);
        self
    }

    fn configure_fonts(&self, cc: &CreationContext) {
        let mut fonts = FontDefinitions::default();

        // Add custom fonts
        fonts.font_data.insert(
            "FiraCode-Regular".to_owned(),
            FontData::from_static(include_bytes!(
                "../assets/fonts/FiraCode-Regular.ttf"
            )),
        );
        fonts.font_data.insert(
            "Roboto-Regular".to_owned(),
            FontData::from_static(include_bytes!(
                "../assets/fonts/Roboto-Regular.ttf"
            )),
        );

        // Use FiraCode for monospace
        fonts
            .families
            .entry(FontFamily::Monospace)
            .or_default()
            .insert(0, "FiraCode-Regular".to_owned());

        // Use Roboto for proportional text
        fonts
            .families
            .entry(FontFamily::Proportional)
            .or_default()
            .insert(0, "Roboto-Regular".to_owned());

        cc.egui_ctx.set_fonts(fonts);
    }

    fn configure_visuals(&self, cc: &CreationContext) {
        // Custom theme
        let visual_config = if self.dark_mode {
            Visuals::dark()
        } else {
            Visuals::light()
        };

        let visuals = Visuals {
            widgets: Widgets {
                noninteractive: WidgetVisuals {
                    bg_fill: if self.dark_mode {
                        Color32::from_gray(30)
                    } else {
                        Color32::WHITE
                    },
                    bg_stroke: Stroke::new(1.0, Color32::from_gray(60)),
                    fg_stroke: Stroke::new(1.0, Color32::from_gray(180)),
                    rounding: Rounding::same(3.0),
                    expansion: 0.0,
                    weak_bg_fill: Color32::from_gray(0),
                },
                inactive: WidgetVisuals {
                    bg_fill: if self.dark_mode {
                        Color32::from_gray(50)
                    } else {
                        Color32::from_gray(245)
                    },
                    bg_stroke: Stroke::new(1.0, Color32::from_gray(80)),
                    fg_stroke: Stroke::new(1.0, Color32::from_gray(180)),
                    rounding: Rounding::same(3.0),
                    expansion: 0.0,
                    weak_bg_fill: Color32::from_gray(0),
                },
                hovered: WidgetVisuals {
                    bg_fill: if self.dark_mode {
                        Color32::from_gray(60)
                    } else {
                        Color32::from_gray(235)
                    },
                    bg_stroke: Stroke::new(1.0, Color32::from_gray(90)),
                    fg_stroke: Stroke::new(1.0, Color32::from_gray(220)),
                    rounding: Rounding::same(3.0),
                    expansion: 0.0,
                    weak_bg_fill: Color32::from_gray(0),
                },
                active: WidgetVisuals {
                    bg_fill: if self.dark_mode {
                        Color32::from_gray(70)
                    } else {
                        Color32::from_gray(225)
                    },
                    bg_stroke: Stroke::new(1.0, Color32::from_gray(100)),
                    fg_stroke: Stroke::new(1.0, Color32::from_gray(255)),
                    rounding: Rounding::same(3.0),
                    expansion: 0.0,
                    weak_bg_fill: Color32::from_gray(0),
                },
                open: WidgetVisuals {
                    bg_fill: if self.dark_mode {
                        Color32::from_gray(80)
                    } else {
                        Color32::from_gray(215)
                    },
                    bg_stroke: Stroke::new(1.0, Color32::from_gray(110)),
                    fg_stroke: Stroke::new(1.0, Color32::from_gray(255)),
                    rounding: Rounding::same(3.0),
                    expansion: 0.0,
                    weak_bg_fill: Color32::from_gray(0),
                },
            },
            ..visual_config
        };

        let mut style = Style::default();
        style.text_styles = [
            (TextStyle::Heading, FontId::proportional(28.0)),
            (TextStyle::Name("Context".into()), FontId::proportional(24.0)),
            (TextStyle::Body, FontId::proportional(18.0)),
            (TextStyle::Monospace, FontId::monospace(16.0)),
            (TextStyle::Button, FontId::proportional(18.0)),
            (TextStyle::Small, FontId::proportional(14.0)),
        ]
        .into();

        cc.egui_ctx.set_visuals(visuals);
        cc.egui_ctx.set_style(style);
    }

    fn log(&mut self, message: impl Into<String>) {
        self.log_messages.push(message.into());
    }
}

impl App for BinaryAnalyzerApp {
    fn update(&mut self, ctx: &Context, frame: &mut Frame) {
        self.handle_file_drop(ctx);
        self.top_panel(ctx);
        self.side_panel(ctx);
        self.central_panel(ctx);
        self.bottom_panel(ctx);
    }
}

impl BinaryAnalyzerApp {
    /// Draws the top menu bar
    fn top_panel(&mut self, ctx: &Context) {
        TopBottomPanel::top("menu_bar").show(ctx, |ui| {
            ui.add_space(4.0);
            menu::bar(ui, |ui| {
                // File Menu
                ui.menu_button(RichText::new("File").size(16.0), |ui| {
                    if ui.button("📂 Open...").clicked() {
                        self.open_file_dialog();
                        ui.close_menu();
                    }
                    if ui.button("🕒 Recent Files").clicked() {
                        // Handle recent files submenu
                        ui.close_menu();
                    }
                    if ui.button("❌ Exit").clicked() {
                        std::process::exit(0);
                    }
                });

                // View Menu
                ui.menu_button(RichText::new("View").size(16.0), |ui| {
                    if ui.checkbox(&mut self.dark_mode, "🌙 Dark Mode").clicked() {
                        let mut visuals = ctx.style().visuals.clone();

                        if self.dark_mode {
                            visuals = Visuals::dark();
                        } else {
                            visuals = Visuals::light();
                        }

                        ctx.set_visuals(visuals);
                        ui.close_menu();
                    }
                    if ui.button("🔄 Refresh").clicked() {
                        self.perform_analysis();
                        ui.close_menu();
                    }
                });

                // Settings
                ui.menu_button(RichText::new("Settings").size(16.0), |ui| {
                    if ui.button("⚙ Preferences").clicked() {
                        self.settings_open = true;
                        ui.close_menu();
                    }
                });

                // Help Menu
                ui.menu_button(RichText::new("Help").size(16.0), |ui| {
                    if ui.button("ℹ About").clicked() {
                        ui.close_menu();
                        self.show_about(ctx);
                    }
                });

                ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
                    ui.label(
                        RichText::new("🦀 Rust Binary Analyzer")
                            .font(FontId::proportional(20.0))
                            .color(Color32::LIGHT_BLUE),
                    );
                });
            });
            ui.add_space(4.0);
        });
    }

    /// Draws the side panel for navigation
    fn side_panel(&mut self, ctx: &Context) {
        SidePanel::left("side_panel")
            .resizable(true)
            .default_width(300.0)
            .min_width(200.0)
            .show(ctx, |ui| {
                ui.add_space(10.0);
                ui.heading("🧭 Explorer");
                ui.separator();

                if !self.analysis_result.is_empty() {
                    // Navigation Tabs
                    ui.horizontal(|ui| {
                        ui.selectable_value(
                            &mut self.navigation_view,
                            NavigationView::Sections,
                            "Sections",
                        );
                        ui.selectable_value(
                            &mut self.navigation_view,
                            NavigationView::Symbols,
                            "Symbols",
                        );
                        ui.selectable_value(
                            &mut self.navigation_view,
                            NavigationView::Strings,
                            "Strings",
                        );
                    });
                    ui.separator();

                    // Search bar
                    ui.add(
                        egui::TextEdit::singleline(&mut self.search_query)
                            .hint_text("🔎 Search...")
                            .desired_width(f32::INFINITY),
                    );
                    ui.add_space(10.0);

                    // Navigation Content
                    ScrollArea::vertical().show(ui, |ui| {
                        match self.navigation_view {
                            NavigationView::Sections => {
                                for section in &self.analysis_result.sections {
                                    let selected = self
                                        .selected_section
                                        .as_ref()
                                        .map_or(false, |s| s.name == section.name);
                                    if ui
                                        .selectable_label(
                                            selected,
                                            format!("📄 {}", section.name),
                                        )
                                        .clicked()
                                    {
                                        self.selected_section = Some(section.clone());
                                        self.selected_symbol = None;
                                        self.selected_string = None;
                                        self.selected_tab = Tab::SectionDetails;
                                    }
                                }
                            }
                            NavigationView::Symbols => {
                                let symbols = if !self.search_query.is_empty() {
                                    let query = self.search_query.to_lowercase();
                                    self.analysis_result
                                        .symbols
                                        .iter()
                                        .filter(|symbol| {
                                            symbol.demangled_name.to_lowercase().contains(&query)
                                        })
                                        .cloned()
                                        .collect::<Vec<SymbolInfo>>()
                                } else {
                                    self.analysis_result.symbols.clone()
                                };

                                for symbol in symbols {
                                    let selected = self
                                        .selected_symbol
                                        .as_ref()
                                        .map_or(false, |s| s.name == symbol.name);
                                    if ui
                                        .selectable_label(
                                            selected,
                                            format!("🔧 {}", symbol.demangled_name),
                                        )
                                        .clicked()
                                    {
                                        self.selected_symbol = Some(symbol.clone());
                                        self.selected_section = None;
                                        self.selected_string = None;
                                        self.selected_tab = Tab::SymbolDetails;
                                    }
                                }
                            }
                            NavigationView::Strings => {
                                let strings = if !self.search_query.is_empty() {
                                    let query = self.search_query.to_lowercase();
                                    self.analysis_result
                                        .strings
                                        .iter()
                                        .filter(|string_info| {
                                            string_info.value.to_lowercase().contains(&query)
                                        })
                                        .cloned()
                                        .collect::<Vec<StringInfo>>()
                                } else {
                                    self.analysis_result.strings.clone()
                                };

                                for string_info in strings {
                                    let selected = self.selected_string.as_ref().map_or(false, |s| {
                                        s.address == string_info.address
                                    });
                                    if ui
                                        .selectable_label(selected, format!("💬 {}", string_info.value))
                                        .clicked()
                                    {
                                        self.selected_string = Some(string_info.clone());
                                        self.selected_section = None;
                                        self.selected_symbol = None;
                                        self.selected_tab = Tab::StringDetails;
                                    }
                                }
                            }
                        }
                    });
                } else {
                    ui.centered_and_justified(|ui| {
                        ui.label("No file loaded.");
                    });
                }
            });
    }

    /// Draws the central panel displaying analysis results
    fn central_panel(&mut self, ctx: &Context) {
        egui::CentralPanel::default().show(ctx, |ui| {
            if self.analysis_result.is_empty() {
                ui.vertical_centered(|ui| {
                    ui.add_space(100.0);
                    ui.label(
                        RichText::new("🦀 Rust Binary Analyzer")
                            .heading()
                            .size(32.0)
                            .color(Color32::LIGHT_BLUE),
                    );
                    ui.add_space(20.0);
                    ui.label(
                        RichText::new(
                            "Drag and drop a binary file here or use 📁 File > 📂 Open to start.",
                        )
                        .italics(),
                    );
                });
            } else {
                self.display_info_panel(ui);

                ui.add_space(5.0);

                // Tab bar for different views
                ui.horizontal(|ui| {
                    ui.selectable_value(
                        &mut self.selected_tab,
                        Tab::SectionDetails,
                        "Section Details",
                    );
                    ui.selectable_value(
                        &mut self.selected_tab,
                        Tab::SymbolDetails,
                        "Symbol Details",
                    );
                    ui.selectable_value(
                        &mut self.selected_tab,
                        Tab::StringDetails,
                        "String Details",
                    );
                    ui.selectable_value(&mut self.selected_tab, Tab::Disassembly, "Disassembly");
                });
                ui.separator();
                ui.add_space(5.0);

                // Display content based on selected tab
                match self.selected_tab {
                    Tab::SectionDetails => self.display_section_details(ui),
                    Tab::SymbolDetails => self.display_symbol_details(ui),
                    Tab::StringDetails => self.display_string_details(ui),
                    Tab::Disassembly => self.display_disassembly(ui),
                }
            }
        });
    }

    /// Displays the information panel at the top of the central panel
    fn display_info_panel(&mut self, ui: &mut Ui) {
        ui.horizontal(|ui| {
            ui.label(RichText::new("Format:").strong());
            ui.monospace(format!("{:?}", self.analysis_result.format));
            ui.separator();
            ui.label(RichText::new("Arch:").strong());
            ui.monospace(format!("{:?}", self.analysis_result.architecture));
            ui.separator();
            ui.label(RichText::new("Endianness:").strong());
            ui.monospace(format!("{:?}", self.analysis_result.endianness));
            ui.separator();
            ui.label(RichText::new("File Size:").strong());
            ui.monospace(format!(
                "{:.2} KB",
                self.analysis_result.file_size as f64 / 1024.0
            ));
        });
    }

    /// Displays the bottom panel with logs or status messages
    fn bottom_panel(&mut self, ctx: &Context) {
        TopBottomPanel::bottom("status_bar").show(ctx, |ui| {
            ui.horizontal(|ui| {
                if !self.binary_path.is_empty() {
                    ui.label(format!("📄 File: {}", self.binary_path));
                }
                ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
                    if self.error_message.is_some() {
                        ui.colored_label(Color32::RED, "Error");
                    } else {
                        ui.label("Ready");
                    }
                });
            });
        });
    }

    /// Displays section details in the central panel
    fn display_section_details(&mut self, ui: &mut Ui) {
        if let Some(section) = &self.selected_section {
            ui.heading(format!("📄 Section: {}", section.name));
            ui.separator();
            Grid::new("section_details_grid")
                .num_columns(2)
                .spacing([40.0, 8.0])
                .show(ui, |ui| {
                    ui.label(RichText::new("Address:").strong());
                    ui.label(format!("0x{:X}", section.address));
                    ui.end_row();
                    ui.label(RichText::new("Size:").strong());
                    ui.label(format!("{}", section.size));
                    ui.end_row();
                    ui.label(RichText::new("Flags:").strong());
                    ui.label(format!("{:?}", section.flags));
                    ui.end_row();
                    ui.label(RichText::new("Type:").strong());
                    ui.label(format!("{:?}", section.kind));
                    ui.end_row();
                    ui.label(RichText::new("Relocation Entries:").strong());
                    ui.label(format!("{}", section.relocations.len()));
                    ui.end_row();
                });
            ui.add_space(10.0);

            ui.collapsing("🔎 Hex View", |ui| {
                ScrollArea::both().show(ui, |ui| {
                    self.display_hex_view(ui, &section.data);
                });
            });
        } else {
            ui.centered_and_justified(|ui| {
                ui.label("Select a section from the left panel to view details.");
            });
        }
    }

    /// Displays symbol details in the central panel
    fn display_symbol_details(&mut self, ui: &mut Ui) {
        if let Some(symbol) = &self.selected_symbol {
            ui.heading(format!("🔧 Symbol: {}", symbol.demangled_name));
            ui.separator();
            Grid::new("symbol_details_grid")
                .num_columns(2)
                .spacing([40.0, 8.0])
                .show(ui, |ui| {
                    ui.label(RichText::new("Name:").strong());
                    ui.label(&symbol.name);
                    ui.end_row();
                    ui.label(RichText::new("Address:").strong());
                    ui.label(format!("0x{:X}", symbol.address));
                    ui.end_row();
                    ui.label(RichText::new("Size:").strong());
                    ui.label(format!("{}", symbol.size));
                    ui.end_row();
                    ui.label(RichText::new("Kind:").strong());
                    ui.label(format!("{:?}", symbol.kind));
                    ui.end_row();
                    ui.label(RichText::new("Scope:").strong());
                    ui.label(format!("{:?}", symbol.scope));
                    ui.end_row();
                    ui.label(RichText::new("Section:").strong());
                    ui.label(format!("{:?}", symbol.section));
                    ui.end_row();
                    ui.label(RichText::new("Import:").strong());
                    ui.label(format!("{}", symbol.is_import));
                    ui.end_row();
                    ui.label(RichText::new("Export:").strong());
                    ui.label(format!("{}", symbol.is_export));
                    ui.end_row();
                });
            ui.add_space(10.0);
        } else {
            ui.centered_and_justified(|ui| {
                ui.label("Select a symbol from the left panel to view details.");
            });
        }
    }

    /// Displays string details in the central panel
    fn display_string_details(&mut self, ui: &mut Ui) {
        if let Some(string_info) = &self.selected_string {
            ui.heading("💬 String Details");
            ui.separator();
            Grid::new("string_details_grid")
                .num_columns(2)
                .spacing([40.0, 8.0])
                .show(ui, |ui| {
                    ui.label(RichText::new("Address:").strong());
                    ui.label(format!("0x{:X}", string_info.address));
                    ui.end_row();
                    ui.label(RichText::new("Value:").strong());
                    ui.label(&string_info.value);
                    ui.end_row();
                });
            ui.add_space(10.0);
        } else {
            ui.centered_and_justified(|ui| {
                ui.label("Select a string from the left panel to view details.");
            });
        }
    }

    /// Displays disassembly of code sections
    fn display_disassembly(&mut self, ui: &mut Ui) {
        if let Some(section) = &self.selected_section {
            if section.is_executable {
                ui.heading(format!("🧩 Disassembly of {}", section.name));
                ui.separator();
                if let Some(disassembly) = self.disassembly_cache.get(&section.address) {
                    ScrollArea::vertical().show(ui, |ui| {
                        self.display_syntax_highlighted_disassembly(ui, disassembly);
                    });
                } else {
                    ui.label("Disassembling...");
                    if let Ok(disassembly) = self.perform_disassembly(section) {
                        self.disassembly_cache
                            .insert(section.address, disassembly.clone());
                        ScrollArea::vertical().show(ui, |ui| {
                            self.display_syntax_highlighted_disassembly(ui, &disassembly);
                        });
                    } else {
                        ui.label("Failed to disassemble section.");
                    }
                }
            } else {
                ui.label("Selected section is not executable.");
            }
        } else if let Some(symbol) = &self.selected_symbol {
            ui.heading(format!("🧩 Disassembly of {}", symbol.demangled_name));
            ui.separator();
            if let Some(disassembly) = self.disassembly_cache.get(&symbol.address) {
                ScrollArea::vertical().show(ui, |ui| {
                    self.display_syntax_highlighted_disassembly(ui, disassembly);
                });
            } else {
                ui.label("Disassembling...");
                if let Ok(disassembly) = self.perform_disassembly_symbol(symbol) {
                    self.disassembly_cache
                        .insert(symbol.address, disassembly.clone());
                    ScrollArea::vertical().show(ui, |ui| {
                        self.display_syntax_highlighted_disassembly(ui, &disassembly);
                    });
                } else {
                    ui.label("Failed to disassemble symbol.");
                }
            }
        } else {
            ui.centered_and_justified(|ui| {
                ui.label("Select an executable section or symbol to disassemble.");
            });
        }
    }

    /// Performs the binary analysis
    fn perform_analysis(&mut self) {
        match analyze_binary(&self.binary_path) {
            Ok(result) => {
                self.analysis_result = result;
                self.error_message = None;
                self.selected_section = None;
                self.selected_symbol = None;
                self.selected_string = None;
                self.disassembly_cache.clear();
                self.log("Analysis completed successfully.");
            }
            Err(e) => {
                self.analysis_result = AnalysisResult::default();
                self.error_message = Some(e.clone());
                self.selected_section = None;
                self.selected_symbol = None;
                self.selected_string = None;
                self.disassembly_cache.clear();
                self.log(format!("Error during analysis: {}", e));
            }
        }
    }

    /// Opens the file dialog to select a binary file
    fn open_file_dialog(&mut self) {
        if let Some(path) = FileDialog::new().pick_file() {
            self.binary_path = path.display().to_string();
            self.perform_analysis();
            self.recent_files.push(self.binary_path.clone());
        }
    }

    /// Displays the hex view of the data
    fn display_hex_view(&self, ui: &mut Ui, data: &[u8]) {
        let bytes_per_row = 16;
        let mut offset = 0;
        ui.separator();
        while offset < data.len() {
            let end = usize::min(offset + bytes_per_row, data.len());
            let row = &data[offset..end];

            let hex_row: String = row.iter().map(|b| format!("{:02X} ", b)).collect();
            let ascii_row: String = row
                .iter()
                .map(|b| {
                    if b.is_ascii_graphic() || b.is_ascii_whitespace() {
                        *b as char
                    } else {
                        '.'
                    }
                })
                .collect();

            ui.horizontal_wrapped(|ui| {
                ui.monospace(format!("{:08X}: ", offset));
                ui.add_space(4.0);
                ui.monospace(&hex_row);
                if end - offset < bytes_per_row {
                    let missing = bytes_per_row - (end - offset);
                    ui.add_space(3.0 * missing as f32 * ui.fonts(|f| f.pixels_per_point()));
                }
                ui.add_space(10.0);
                ui.monospace(&ascii_row);
            });

            offset += bytes_per_row;
        }
    }

    /// Performs disassembly on the given section
    fn perform_disassembly(&self, section: &SectionInfo) -> Result<String, String> {
        let cs = Capstone::new()
            .x86()
            .mode(self.analysis_result.capstone_mode)
            .syntax(capstone::arch::x86::ArchSyntax::Intel)
            .detail(true)
            .build()
            .map_err(|e| format!("Capstone error: {}", e))?;

        let insns = cs
            .disasm_all(&section.data, section.address)
            .map_err(|e| format!("Disassembly error: {}", e))?;

        let mut disassembly = String::new();
        for i in insns.iter() {
            disassembly.push_str(&format!(
                "{:08X}  {:<8} {}\n",
                i.address(),
                i.mnemonic().unwrap_or(""),
                i.op_str().unwrap_or(""),
            ));
        }
        Ok(disassembly)
    }

    /// Performs disassembly on the given symbol
    fn perform_disassembly_symbol(&self, symbol: &SymbolInfo) -> Result<String, String> {
        let cs = Capstone::new()
            .x86()
            .mode(self.analysis_result.capstone_mode)
            .syntax(ArchSyntax::Intel)
            .detail(true)
            .build()
            .map_err(|e| format!("Capstone error: {}", e))?;

        // Find the section containing the symbol
        if let Some(section) = self
            .analysis_result
            .sections
            .iter()
            .find(|s| symbol.address >= s.address && symbol.address < s.address + s.size)
        {
            let start = (symbol.address - section.address) as usize;
            let end = start + symbol.size as usize;
            let data = &section.data[start..end];

            let insns = cs
                .disasm_all(data, symbol.address)
                .map_err(|e| format!("Disassembly error: {}", e))?;

            let mut disassembly = String::new();
            for i in insns.iter() {
                disassembly.push_str(&format!(
                    "{:08X}  {:<8} {}\n",
                    i.address(),
                    i.mnemonic().unwrap_or(""),
                    i.op_str().unwrap_or(""),
                ));
            }
            Ok(disassembly)
        } else {
            Err("Symbol not found in any section.".to_string())
        }
    }

    /// Display disassembly with basic syntax highlighting
    fn display_syntax_highlighted_disassembly(&self, ui: &mut Ui, disassembly: &str) {
        for line in disassembly.lines() {
            if line.trim().is_empty() {
                continue;
            }
            let parts: Vec<&str> = line.splitn(3, ' ').collect();
            if parts.len() >= 3 {
                ui.horizontal(|ui| {
                    ui.monospace(parts[0]);
                    ui.add_space(8.0);
                    ui.colored_label(Color32::YELLOW, parts[1]);
                    ui.add_space(8.0);
                    ui.monospace(parts[2..].join(" "));
                });
            } else {
                ui.monospace(line);
            }
        }
    }

    /// Shows the About dialog
    fn show_about(&self, ctx: &Context) {
        egui::Window::new("About Rust Binary Analyzer")
            .anchor(Align2::CENTER_CENTER, [0.0, 0.0])
            .collapsible(false)
            .resizable(false)
            .show(ctx, |ui| {
                ui.vertical_centered(|ui| {
                    ui.heading("🦀 Rust Binary Analyzer");
                    ui.separator();
                    ui.label("Version 1.0.0");
                    ui.label("Developed with 💖 using Rust and egui");
                    ui.hyperlink_to(
                        "GitHub Repository",
                        "https://github.com/yourusername/rust-binary-analyzer",
                    );
                });
            });
    }

    /// Handles file drop events
    fn handle_file_drop(&mut self, ctx: &egui::Context) {
        if !ctx.input(|i| i.raw.dropped_files.is_empty()) {
            for file in ctx.input(|i| i.raw.dropped_files.clone()).iter() {
                if let Some(path) = file.path.clone() {
                    self.binary_path = path.display().to_string();
                    self.perform_analysis();
                    // Only process the first file
                    break;
                }
            }
        }
    }
}

/// Represents the different tabs in the central panel
#[derive(PartialEq, Eq, Clone, Copy)]
enum Tab {
    SectionDetails,
    SymbolDetails,
    StringDetails,
    Disassembly,
}

#[derive(PartialEq, Eq, Clone, Copy)]
enum NavigationView {
    Sections,
    Symbols,
    Strings,
}

struct AnalysisResult {
    format: object::BinaryFormat,
    architecture: object::Architecture,
    endianness: object::Endianness,
    capstone_mode: capstone::arch::x86::ArchMode,
    file_size: u64,
    sections: Vec<SectionInfo>,
    symbols: Vec<SymbolInfo>,
    strings: Vec<StringInfo>,
}

impl Default for AnalysisResult {
    fn default() -> Self {
        AnalysisResult {
            format: object::BinaryFormat::Elf,
            architecture: object::Architecture::Unknown,
            endianness: object::Endianness::Little,
            capstone_mode: capstone::arch::x86::ArchMode::Mode64.into(),
            file_size: 0,
            sections: Vec::new(),
            symbols: Vec::new(),
            strings: Vec::new(),
        }
    }
}

impl AnalysisResult {
    fn is_empty(&self) -> bool {
        self.sections.is_empty() && self.symbols.is_empty() && self.strings.is_empty()
    }
}

#[derive(Clone)]
struct SectionInfo {
    name: String,
    address: u64,
    size: u64,
    data: Vec<u8>,
    flags: object::SectionFlags,
    kind: SectionKind,
    relocations: Arc<Vec<object::Relocation>>,
    is_executable: bool,
}

#[derive(Clone)]
struct StringInfo {
    address: u64,
    value: String,
}

fn analyze_binary(path: &str) -> Result<AnalysisResult, String> {
    let mut file = File::open(path).map_err(|e| format!("Failed to open file: {}", e))?;
    let metadata = file
        .metadata()
        .map_err(|e| format!("Failed to get file metadata: {}", e))?;
    let file_size = metadata.len();

    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer)
        .map_err(|e| format!("Failed to read file: {}", e))?;

    let obj_file =
        object::File::parse(&*buffer).map_err(|e| format!("Failed to parse binary: {}", e))?;

    let mut sections = Vec::new();
    for section in obj_file.sections() {
        let data = section
            .uncompressed_data()
            .unwrap_or(Cow::Borrowed(&[]))
            .to_vec();
        let is_executable = section.kind() == SectionKind::Text;
        let section_info = SectionInfo {
            name: section.name().unwrap_or("Unknown").to_string(),
            address: section.address(),
            size: section.size(),
            data,
            flags: section.flags(),
            kind: section.kind(),
            relocations: Arc::new(section.relocations().map(|(_, reloc)| reloc).collect()),
            is_executable,
        };
        sections.push(section_info);
    }

    // Use the extract_symbols function from symbol.rs
    let symbols = extract_symbols(&obj_file);

    // Extract strings from the collected sections
    let strings = extract_strings(&sections);

    // Determine Capstone architecture and mode based on object file architecture
    let capstone_mode = get_capstone_mode(&obj_file);

    Ok(AnalysisResult {
        format: obj_file.format(),
        architecture: obj_file.architecture(),
        endianness: obj_file.endianness(),
        capstone_mode,
        file_size,
        sections,
        symbols,
        strings,
    })
}

/// Maps object architecture to Capstone mode
fn get_capstone_mode(obj_file: &object::File) -> capstone::arch::x86::ArchMode {
    match obj_file.architecture() {
        object::Architecture::X86_64 => capstone::arch::x86::ArchMode::Mode64.into(),
        object::Architecture::I386 => capstone::arch::x86::ArchMode::Mode32.into(),
        _ => capstone::arch::x86::ArchMode::Mode64.into(),
    }
}

/// Extract printable ASCII strings from the sections likely to contain strings
fn extract_strings(sections: &[SectionInfo]) -> Vec<StringInfo> {
    let mut strings = Vec::new();

    for section in sections {
        // Check if the section is likely to contain strings
        if !section.name.contains(".rodata")
            && !section.name.contains(".data")
            && !section.name.contains(".rdata")
            && !section.name.contains(".text")
        {
            continue;
        }

        let data = &section.data;
        let mut i = 0;
        while i < data.len() {
            // Skip non-printable characters
            while i < data.len()
                && !(data[i].is_ascii_graphic() || data[i].is_ascii_whitespace())
            {
                i += 1;
            }
            let start = i;
            // Collect printable ASCII characters
            while i < data.len()
                && (data[i].is_ascii_graphic() || data[i].is_ascii_whitespace())
            {
                i += 1;
            }
            let end = i;
            // If the collected string is long enough, add it to the list
            if end - start >= 4 {
                if let Ok(s) = String::from_utf8(data[start..end].to_vec()) {
                    strings.push(StringInfo {
                        address: section.address + start as u64,
                        value: s,
                    });
                }
            }
        }
    }

    strings
}

symbol.rs:


use object::{Object, ObjectSymbol, ObjectSymbolTable, SymbolKind, SymbolScope, SymbolSection};
use rustc_demangle::demangle;
use std::collections::HashMap;

/// Represents detailed information about a symbol.
#[derive(Clone)]
pub struct SymbolInfo {
    pub name: String,
    pub demangled_name: String,
    pub address: u64,
    pub size: u64,
    pub kind: SymbolKind,
    pub scope: SymbolScope,
    pub section: SymbolSection,
    pub is_import: bool,
    pub is_export: bool,
}

/// Extracts symbols from the given object file, including dynamic and debug symbols.
/// It returns a vector of SymbolInfo with detailed information about each symbol.
pub fn extract_symbols<'data, 'file>(
    obj_file: &object::File<'data>,
) -> Vec<SymbolInfo> {
    let mut symbols = Vec::new();

    // Collect symbols from the symbol table
    for symbol in obj_file.symbols() {
        if let Some(symbol_info) = process_symbol(&symbol) {
            symbols.push(symbol_info);
        }
    }

    // Collect dynamic symbols (useful for shared libraries and executables)
    for symbol in obj_file.dynamic_symbols() {
        if let Some(symbol_info) = process_symbol(&symbol) {
            symbols.push(symbol_info);
        }
    }
    // Optionally, collect symbols from debug sections if available
    if let Some(symbol_table) = obj_file.symbol_table() {
        for symbol in symbol_table.symbols() {
            if let Some(symbol_info) = process_symbol(&symbol) {
                symbols.push(symbol_info);
            }
        }
    }

    // Remove duplicates based on the symbol's address and name
    let mut seen = HashMap::new();
    symbols.retain(|s| {
        let key = (s.address, s.name.clone());
        if seen.contains_key(&key) {
            false
        } else {
            seen.insert(key, true);
            true
        }
    });

    // Sort symbols by address
    symbols.sort_by_key(|s| s.address);

    symbols
}

/// Processes a single symbol and returns Some(SymbolInfo) if valid, or None otherwise.
fn process_symbol<'data, 'file>(symbol: &object::Symbol<'data, 'file>) -> Option<SymbolInfo> {
    if symbol.address() == 0 {
        return None;
    }

    if symbol.kind() == SymbolKind::Section {
        return None;
    }

    if let Ok(name) = symbol.name() {
        let demangled_name = demangle(name).to_string();
        Some(SymbolInfo {
            name: name.to_string(),
            demangled_name,
            address: symbol.address(),
            size: symbol.size(),
            kind: symbol.kind(),
            scope: symbol.scope(),
            section: symbol.section(),
            is_import: false,
            is_export: false,
        })
    } else {
        None
    }
}