<commit_before>use alloc::vec::Vec;
use core::fmt::Debug;
use core::{mem, str};

use core::convert::TryInto;

use crate::read::coff::{CoffCommon, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, SymbolTable};
use crate::read::{
    self, Architecture, ComdatKind, Error, Export, FileFlags, Import, NoDynamicRelocationIterator,
    Object, ObjectComdat, ReadError, ReadRef, Result, SectionIndex, SymbolIndex,
};
use crate::{
    pe, ByteString, Bytes, CodeView, LittleEndian as LE, Pod, U16Bytes, U32Bytes, U32, U64,
};

use super::{PeSection, PeSectionIterator, PeSegment, PeSegmentIterator, SectionTable};

/// A PE32 (32-bit) image file.
pub type PeFile32<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders32, R>;
/// A PE32+ (64-bit) image file.
pub type PeFile64<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders64, R>;

/// A PE object file.
#[derive(Debug)]
pub struct PeFile<'data, Pe, R = &'data [u8]>
where
    Pe: ImageNtHeaders,
    R: ReadRef<'data>,
{
    pub(super) dos_header: &'data pe::ImageDosHeader,
    pub(super) nt_headers: &'data Pe,
    pub(super) data_directories: &'data [pe::ImageDataDirectory],
    pub(super) common: CoffCommon<'data>,
    pub(super) data: R,
}

impl<'data, Pe, R> PeFile<'data, Pe, R>
where
    Pe: ImageNtHeaders,
    R: ReadRef<'data>,
{
    /// Parse the raw PE file data.
    pub fn parse(data: R) -> Result<Self> {
        let dos_header = pe::ImageDosHeader::parse(data)?;
        let mut offset = dos_header.nt_headers_offset().into();
        let (nt_headers, data_directories) = Pe::parse(data, &mut offset)?;
        let sections = nt_headers.sections(data, offset)?;
        let symbols = nt_headers.symbols(data)?;
        let image_base = nt_headers.optional_header().image_base();

        Ok(PeFile {
            dos_header,
            nt_headers,
            data_directories,
            common: CoffCommon {
                sections,
                symbols,
                image_base,
            },
            data,
        })
    }

    pub(super) fn section_alignment(&self) -> u64 {
        u64::from(self.nt_headers.optional_header().section_alignment())
    }

    /// Return the DOS header of this file
    pub fn dos_header(&self) -> &'data pe::ImageDosHeader {
        self.dos_header
    }

    /// Return the NT Headers of this file
    pub fn nt_headers(&self) -> &'data Pe {
        self.nt_headers
    }

    fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> {
        self.data_directories
            .get(id)
            .filter(|d| d.size.get(LE) != 0)
    }

    fn data_at(&self, va: u32) -> Option<Bytes<'data>> {
        self.common.sections.pe_data_at(self.data, va).map(Bytes)<commit_msg>Expose PeFile data, section_table and data_directory<commit_after>use alloc::vec::Vec;
use core::fmt::Debug;
use core::{mem, str};

use core::convert::TryInto;

use crate::read::coff::{CoffCommon, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, SymbolTable};
use crate::read::{
    self, Architecture, ComdatKind, Error, Export, FileFlags, Import, NoDynamicRelocationIterator,
    Object, ObjectComdat, ReadError, ReadRef, Result, SectionIndex, SymbolIndex,
};
use crate::{
    pe, ByteString, Bytes, CodeView, LittleEndian as LE, Pod, U16Bytes, U32Bytes, U32, U64,
};

use super::{PeSection, PeSectionIterator, PeSegment, PeSegmentIterator, SectionTable};

/// A PE32 (32-bit) image file.
pub type PeFile32<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders32, R>;
/// A PE32+ (64-bit) image file.
pub type PeFile64<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders64, R>;

/// A PE object file.
#[derive(Debug)]
pub struct PeFile<'data, Pe, R = &'data [u8]>
where
    Pe: ImageNtHeaders,
    R: ReadRef<'data>,
{
    pub(super) dos_header: &'data pe::ImageDosHeader,
    pub(super) nt_headers: &'data Pe,
    pub(super) data_directories: &'data [pe::ImageDataDirectory],
    pub(super) common: CoffCommon<'data>,
    pub(super) data: R,
}

impl<'data, Pe, R> PeFile<'data, Pe, R>
where
    Pe: ImageNtHeaders,
    R: ReadRef<'data>,
{
    /// Parse the raw PE file data.
    pub fn parse(data: R) -> Result<Self> {
        let dos_header = pe::ImageDosHeader::parse(data)?;
        let mut offset = dos_header.nt_headers_offset().into();
        let (nt_headers, data_directories) = Pe::parse(data, &mut offset)?;
        let sections = nt_headers.sections(data, offset)?;
        let symbols = nt_headers.symbols(data)?;
        let image_base = nt_headers.optional_header().image_base();

        Ok(PeFile {
            dos_header,
            nt_headers,
            data_directories,
            common: CoffCommon {
                sections,
                symbols,
                image_base,
            },
            data,
        })
    }

    pub(super) fn section_alignment(&self) -> u64 {
        u64::from(self.nt_headers.optional_header().section_alignment())
    }

    /// Return the DOS header of this file
    pub fn dos_header(&self) -> &'data pe::ImageDosHeader {
        self.dos_header
    }

    /// Return the NT Headers of this file
    pub fn nt_headers(&self) -> &'data Pe {
        self.nt_headers
    }

    /// Returns the section table of this binary.
    pub fn section_table(&self) -> SectionTable<'data> {
        self.common.sections
    }

    /// Returns the data directory at the given index.
    pub fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> {
        self.data_directories
            .get(id)
            .filter(|d| d.size.get(LE) != 0)
    }

    fn data_at(&self, va: u32) -> Option<Bytes<'data>> {
        self.common.sections.pe_data_at(self.data, va).map(Bytes)
    }

    /// Returns this binary data.
    pub fn data(&self) -> R {
        self.data
{'fraction_non_alphanumeric': 0.1420415224913495, 'fraction_numerical': 0.011764705882352941, 'mean_word_length': 2.954172366621067, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5283097', 'n_tokens_mistral': 1935, 'n_tokens_neox': 1910, 'n_words': 472}