elio 1.3.0

Snappy, batteries-included terminal file manager with rich previews, inline images, bulk actions, and trash support.
Documentation
use super::{BinaryMetadata, ByteOrder, format_hex, read_u16_le, read_u32_le};

pub(super) fn parse(bytes: &[u8]) -> Option<BinaryMetadata> {
    if bytes.get(0..2) != Some(b"MZ".as_slice()) {
        return None;
    }

    let pe_offset = read_u32_le(bytes, 0x3c)? as usize;
    if bytes.get(pe_offset..pe_offset + 4) != Some(b"PE\0\0".as_slice()) {
        return None;
    }

    let coff = pe_offset + 4;
    let machine = read_u16_le(bytes, coff)?;
    let section_count = usize::from(read_u16_le(bytes, coff + 2)?);
    let optional_size = usize::from(read_u16_le(bytes, coff + 16)?);
    let characteristics = read_u16_le(bytes, coff + 18)?;
    let optional = coff + 20;
    let optional_magic = read_u16_le(bytes, optional)?;

    let bits = match optional_magic {
        0x10b => Some("32-bit"),
        0x20b => Some("64-bit"),
        _ => None,
    };
    let subsystem_offset = match optional_magic {
        0x10b => optional + 68,
        0x20b => optional + 88,
        _ => optional,
    };
    let subsystem = if optional + optional_size >= subsystem_offset + 2 {
        read_u16_le(bytes, subsystem_offset).and_then(subsystem_name)
    } else {
        None
    };
    let entry_point = if optional + optional_size >= optional + 20 {
        read_u32_le(bytes, optional + 16).map(|value| format_hex(u64::from(value)))
    } else {
        None
    };

    let is_dll = characteristics & 0x2000 != 0;
    let kind = if is_dll {
        Some("Dynamic library".to_string())
    } else if characteristics & 0x0002 != 0 {
        Some("Executable".to_string())
    } else {
        Some("COFF image".to_string())
    };

    Some(BinaryMetadata {
        detail: if is_dll {
            "PE dynamic library"
        } else {
            "PE executable"
        },
        format: "PE/COFF",
        kind,
        architecture: machine_name(machine).map(str::to_string),
        bits,
        endianness: Some(ByteOrder::Little.label()),
        abi: None,
        subsystem: subsystem.map(str::to_string),
        entry_point,
        section_count: Some(section_count),
        command_count: None,
    })
}

pub(super) fn parse_dos_mz(bytes: &[u8]) -> Option<BinaryMetadata> {
    if bytes.get(0..2) != Some(b"MZ".as_slice()) {
        return None;
    }

    Some(BinaryMetadata {
        detail: "DOS executable",
        format: "MZ",
        kind: Some("Executable".to_string()),
        architecture: Some("x86".to_string()),
        bits: Some("16-bit"),
        endianness: Some(ByteOrder::Little.label()),
        abi: None,
        subsystem: None,
        entry_point: None,
        section_count: None,
        command_count: None,
    })
}

fn machine_name(machine: u16) -> Option<&'static str> {
    match machine {
        0x014c => Some("x86"),
        0x8664 => Some("x86_64"),
        0x01c0 => Some("ARM"),
        0x01c4 => Some("ARMv7"),
        0xaa64 => Some("AArch64"),
        0x5032 => Some("RISC-V 32"),
        0x5064 => Some("RISC-V 64"),
        0x5128 => Some("RISC-V 128"),
        _ => None,
    }
}

fn subsystem_name(subsystem: u16) -> Option<&'static str> {
    match subsystem {
        1 => Some("Native"),
        2 => Some("GUI"),
        3 => Some("Console"),
        5 => Some("OS/2 console"),
        7 => Some("POSIX console"),
        9 => Some("Windows CE"),
        10 => Some("EFI application"),
        11 => Some("EFI boot service driver"),
        12 => Some("EFI runtime driver"),
        13 => Some("EFI ROM"),
        14 => Some("Xbox"),
        16 => Some("Windows boot application"),
        _ => None,
    }
}