hao 0.0.2-prerelease

.net binary reader
Documentation
use super::md::image_headers::ImageCor20Header;
use super::md::streams::MetadataStreams;
use crate::dotnet::md::metadata_header::{MetadataHeader, MetadataType};
use crate::error::{HaoError, Result};
use crate::io::PEImage;

pub struct Metadata<'a> {
    pub metadata_streams: MetadataStreams<'a>,
}

impl<'a> Metadata<'a> {
    pub fn parse(buffer: &'a [u8]) -> Result<Self> {
        let pe_image = PEImage::load_bytes(buffer)?;

        let clr_rt = pe_image.read_clr_rt_header()?;

        let cor20_header = {
            let mut clr_reader = pe_image.create_reader(clr_rt.virtual_address, Some(0x48))?;
            ImageCor20Header::from_reader(&mut clr_reader)
                .map_err(|_| HaoError::BadImageFormat("Failed to read image cor20 header"))?
        };

        if cor20_header.metadata.virtual_address == 0 {
            return Err(HaoError::BadImageFormat(".NET metadata RVA is 0"));
        }

        let metadata_header = {
            let mut md_header_reader =
                pe_image.create_reader(cor20_header.metadata.virtual_address, None)?;
            MetadataHeader::from_reader(&mut md_header_reader)?
        };

        match metadata_header.metadata_type()? {
            MetadataType::Compressed => {}
            MetadataType::Enc => panic!("Only compressed streams are currently supported"),
        };

        let metadata_streams = MetadataStreams::from_headers(
            &pe_image,
            &metadata_header.streams,
            cor20_header.metadata.virtual_address,
        )?;

        Ok(Self { metadata_streams })
    }
}