hao 0.0.3

.net binary reader
Documentation
use std::{fmt::Debug, marker::PhantomData};

use super::{TableLocation, TablesStreamsHeader};
use crate::{
    error::{HaoError, Result},
    io::{DataReader, ReadData},
};

pub struct TablesStreamReader<'a> {
    pub reader: DataReader<'a>,
    pub header: &'a TablesStreamsHeader,
}

impl<'a> TablesStreamReader<'a> {
    pub fn new(tables_stream_data: &'a [u8], header: &'a TablesStreamsHeader) -> Self {
        Self {
            reader: DataReader::new(tables_stream_data),
            header,
        }
    }

    pub fn read_table_offset(&mut self, target_table_size: TableLocation) -> Result<u32> {
        if target_table_size.rows.is_large() {
            self.read()
        } else {
            let small_val: u16 = self.read()?;
            Ok(small_val as u32)
        }
    }

    pub fn read_rows<T: Debug>(&mut self, table_location: TableLocation) -> Result<Vec<T>>
    where
        Self: ReadData<T>,
    {
        let row_count = table_location.rows.0 as usize;
        let mut data = Vec::with_capacity(row_count);
        for _ in 0..row_count {
            data.push(self.read()?);
        }
        Ok(data)
    }
}

impl<'a, T> ReadData<T> for TablesStreamReader<'a>
where
    DataReader<'a>: ReadData<T>,
{
    fn read(&mut self) -> Result<T> {
        self.reader.read()
    }
}

pub struct TableRowsIterator<'a, T>
where
    TablesStreamReader<'a>: ReadData<T>,
{
    reader: TablesStreamReader<'a>,
    index: usize,
    rows: usize,
    _marker: PhantomData<T>,
}

impl<'a, T> TableRowsIterator<'a, T>
where
    TablesStreamReader<'a>: ReadData<T>,
{
    pub fn new(
        heap_data: &'a [u8],
        header: &'a TablesStreamsHeader,
        location: TableLocation,
    ) -> Result<Self> {
        let length = location.rows.0 as usize * location.row_size;
        let slice = heap_data
            .get(location.start_offset..location.start_offset + length)
            .ok_or_else(|| HaoError::InvalidStreamIndex("#~", location.start_offset + length))?;

        Ok(Self {
            reader: TablesStreamReader::new(slice, header),
            index: 0,
            rows: location.rows.0 as usize,
            _marker: PhantomData,
        })
    }
}

impl<'a, T> Iterator for TableRowsIterator<'a, T>
where
    TablesStreamReader<'a>: ReadData<T>,
{
    type Item = Result<T>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index >= self.rows {
            return None;
        }
        self.index += 1;
        Some(self.reader.read())
    }
}