macho2 0.6.2

A better MachO parser library
Documentation
use std::{
    env,
    fs::File,
    io::{stdout, Read, Seek, Write},
};

use macho2::{
    header::MHMagic,
    macho::{FatMachO, MachO, MachOErr, MachOResult},
};

fn main() -> MachOResult<()> {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        eprintln!("Usage: {} <file_path>", args[0]);
        return Ok(());
    }

    let file_path = &args[1];
    let mut file = match File::open(file_path) {
        Ok(file) => file,
        Err(e) => {
            eprintln!("Failed to open file: {}", e);
            return Ok(());
        }
    };

    let mut buffer = Vec::new();
    if let Err(e) = file.read_to_end(&mut buffer) {
        eprintln!("Failed to read file: {}", e);
        return Ok(());
    }

    if buffer.len() < std::mem::size_of::<MHMagic>() {
        eprintln!("File too short to be a Mach-O file");
        return Ok(());
    }

    if FatMachO::<_>::is_fat_magic(&mut file)? {
        let mut fat_macho = FatMachO::<_>::parse(&mut file).unwrap();
        println!("This is a fat macho file. Please select an architecture:");
        for (i, arch) in fat_macho.archs.iter().enumerate() {
            println!("{}: {:?} {:?}", i, arch.cputype(), arch.cpusubtype());
        }
        print!("> ");

        let index = loop {
            let mut input = String::new();
            stdout().flush().unwrap();
            std::io::stdin().read_line(&mut input).unwrap();
            match input.trim().parse::<usize>() {
                Ok(i) if i < fat_macho.archs.len() => break i,
                _ => println!(
                    "Please enter a valid number between 0 and {}",
                    fat_macho.archs.len() - 1
                ),
            }
        };
        let macho = fat_macho.macho(fat_macho.archs[index].cputype())?;
        print_nm(macho);
    } else if MachO::<_>::is_macho_magic(&mut file)? {
        let macho = MachO::<_>::parse(file).unwrap();
        print_nm(macho);
    } else {
        return Err(MachOErr::InvalidValue("Invalid Mach-O file".to_string()));
    };

    Ok(())
}

fn print_nm<T: Read + Seek>(mut macho: MachO<T>) {
    if let Some(dyldinfo) = macho.resolve_dyldinfo() {
        println!("{:?}", dyldinfo);
    }

    if let Some(exportstrie) = macho.resolve_dyldexportstrie() {
        println!("{:?}", exportstrie);
    }
}