hao 0.0.1-prerelease

.net binary reader
Documentation
use crate::{
    dotnet::{
        entries::{Field, Method, Ptr, RowRange},
        md::streams::{
            tables_stream::{
                BlobStreamOffset, FieldTableOffset, GuidStreamOffset,
                MethodTableOffset, StringsStreamOffset,
            },
            MetadataStreams, Signature,
        },
        module::{GetEntry, MaybeUninitEntries},
    },
    error::Result,
};

pub trait ValueReadable<T> {
    type EntryValue;
    fn read(&self, identifier: T) -> Result<Self::EntryValue>;
}

pub struct EntryReader<'a> {
    pub(crate) streams: &'a MetadataStreams<'a>,
    pub(crate) entries: &'a MaybeUninitEntries,
}

impl<'a> EntryReader<'a> {
    pub(crate) fn from_metadata(
        streams: &'a MetadataStreams<'a>,
        entries: &'a MaybeUninitEntries,
    ) -> Self {
        Self { streams , entries  }
    }
}

impl<'a, T> ValueReadable<T> for EntryReader<'a>
where
    MaybeUninitEntries: GetEntry<T>,
{
    type EntryValue = <MaybeUninitEntries as GetEntry<T>>::EntryValue;
    fn read(&self, identifier: T) -> Result<Self::EntryValue> {
        self.entries.get_entry(identifier)
    }
}
 
impl<'a> ValueReadable<u16> for EntryReader<'a> {
    type EntryValue = u16;

    fn read(&self, identifier: u16) -> Result<Self::EntryValue> {
        Ok(identifier)
    }
}

impl<'a> ValueReadable<StringsStreamOffset> for EntryReader<'a> {
    type EntryValue = String;

    fn read(&self, identifier: StringsStreamOffset) -> Result<Self::EntryValue> {
        self.streams
            .strings_stream
            .read_string(identifier.0)
            .map(String::from)
    }
}

impl<'a> ValueReadable<GuidStreamOffset> for EntryReader<'a> {
    type EntryValue = uuid::Uuid;

    fn read(&self, identifier: GuidStreamOffset) -> Result<Self::EntryValue> {
        self.streams.guid_stream.read_guid(identifier.0)
    }
}

impl<'a> ValueReadable<BlobStreamOffset> for EntryReader<'a> {
    type EntryValue = Signature;

    fn read(&self, identifier: BlobStreamOffset) -> Result<Self::EntryValue> {
        let reader = self
            .streams
            .blob_stream
            .get_signature_reader(identifier.0, self.entries)?;
        Signature::from_reader(reader)
    }
}

impl<'a> ValueReadable<RowRange<FieldTableOffset>> for EntryReader<'a> {
    type EntryValue = Vec<Ptr<Field>>;

    fn read(&self, identifier: RowRange<FieldTableOffset>) -> Result<Self::EntryValue> {
        let target_rows = &self.entries.fields;

        let start = identifier.start.0 as usize;
        let end = identifier
            .end
            .map(|c| c.0 as usize)
            .unwrap_or(target_rows.len());

        let slice = target_rows.get(start..end).unwrap_or(&target_rows[start..]);
        Ok(slice.to_vec())
    }
}

impl<'a> ValueReadable<RowRange<MethodTableOffset>> for EntryReader<'a> {
    type EntryValue = Vec<Ptr<Method>>;

    fn read(&self, identifier: RowRange<MethodTableOffset>) -> Result<Self::EntryValue> {
        let target_rows = &self.entries.methods;

        let start = identifier.start.0 as usize;
        let end = identifier
            .end
            .map(|c| c.0 as usize)
            .unwrap_or(target_rows.len());

        let slice = target_rows.get(start..end).unwrap_or(&target_rows[start..]);
        Ok(slice.to_vec())
    }
}