hao 0.0.3

.net binary reader
Documentation
use crate::{
    error::{HaoError, Result},
    io::DataReader,
};

#[derive(Debug, Clone)]
pub struct StringsStream<'a> {
    pub heap_data: &'a [u8],
}

impl<'a> StringsStream<'a> {
    pub fn from_reader(reader: DataReader<'a>) -> Result<Self> {
        Ok(Self {
            heap_data: reader.remaning_slice(),
        })
    }

    pub fn read_string(&self, offset: u32) -> Result<&str> {
        let offset = offset as usize;

        if offset > self.heap_data.len() {
            return Err(HaoError::InvalidStreamIndex("#Strings", offset));
        }

        let slice = &self.heap_data[offset..];
        let terminator = slice
            .iter()
            .position(|c| *c == 0)
            .ok_or_else(|| HaoError::InvalidStreamIndex("#Strings", offset))?;

        std::str::from_utf8(&slice[..terminator])
            .map_err(|_| HaoError::InvalidUTF8String(offset, Vec::from(&slice[..terminator])))
    }
}

#[derive(Debug, Clone)]
pub struct GuidStream<'a> {
    pub heap_data: &'a [u8],
}

impl<'a> GuidStream<'a> {
    pub fn from_reader(reader: DataReader<'a>) -> Result<Self> {
        Ok(Self {
            heap_data: reader.remaning_slice(),
        })
    }

    pub fn read_guid(&self, offset: u32) -> Result<uuid::Uuid> {
        const GUID_SIZE: usize = 16;

        if offset == 0 {
            return Ok(uuid::Uuid::nil());
        }

        let position = (offset - 1) as usize * GUID_SIZE;

        uuid::Uuid::from_slice(&self.heap_data[position..])
            .map_err(|_| HaoError::InvalidStreamIndex("#GUID", position))
    }
}