rustbin 0.8.0

Parsers for binary file formats (mostly Windows related).
Documentation
use std::fmt::Display;

use byteorder::{LittleEndian, ByteOrder};

use crate::{pe::{section::{self, SectionTable}, PeError}, types::{BufReadExt, HeaderField}};

use super::ImportName;

#[derive(Debug, Default)]
pub struct ImportLookup64 {
    pub value: HeaderField<u64>,
    pub is_ordinal: bool,
    pub ordinal: Option<u16>,
    pub iname: Option<HeaderField<ImportName>>,
}

impl Display for ImportLookup64 {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        
        if self.is_ordinal {
            write!(f, "{}", self.ordinal.unwrap_or(u16::MAX))
        }
        else {
            let name = if let Some(name_hdr) = &self.iname {
                format!("{}", name_hdr.value)
            }
            else {
                String::from("ERR")
            };

            write!(f, "{}", name)
        }
    }
}

impl ImportLookup64 {
    pub fn new(value: HeaderField<u64>) -> Self {
        let val = value.value;
        let is_ordinal = (val & (1<<63)) != 0;
        let mut ordinal = None;
        let mut name = None;

        if is_ordinal {
            ordinal = Some(val as u16);
        }
        else {
            let iname_rva = (val as u32) & 0x7FFFFFFF;
            name = Some(HeaderField{value: Default::default(), offset: 0, rva: iname_rva as u64});
        }

        Self { 
            value: value, 
            is_ordinal: is_ordinal,
            ordinal: ordinal,
            iname: name, 
        }
    }

    pub fn update_name(&mut self, sections: &SectionTable, reader: &mut dyn BufReadExt) -> crate::Result<()> {
        if let Some(iname) = &mut self.iname {
            let offset = section::rva_to_offset(sections, iname.rva as u32).ok_or(PeError::InvalidRVA(iname.rva))?;
            let hint = reader.read_bytes_at_offset(offset.into(), 2)?;
            let hint = LittleEndian::read_u16(&hint);
            let name = reader.read_string_at_offset((offset+2).into())?;
            iname.offset = offset.into();
            iname.value = ImportName {
                hint: HeaderField { value: hint, offset: offset.into(), rva: iname.rva },
                name: HeaderField { value: name, offset: (offset+2).into(), rva: iname.rva+2 }
            };
        }
        Ok(())
    }
}