use std::io::{Read, Seek};
use crate::error::{Error, Result};
use crate::io::reader::HdfReader;
const HEAP_MAGIC: [u8; 4] = [b'H', b'E', b'A', b'P'];
#[derive(Debug, Clone)]
pub struct LocalHeap {
pub data: Vec<u8>,
}
impl LocalHeap {
pub fn read_at<R: Read + Seek>(reader: &mut HdfReader<R>, addr: u64) -> Result<Self> {
reader.seek(addr)?;
let magic = reader.read_bytes(4)?;
if magic != HEAP_MAGIC {
return Err(Error::InvalidFormat("invalid local heap magic".into()));
}
let version = reader.read_u8()?;
if version != 0 {
return Err(Error::Unsupported(format!(
"local heap version {version}"
)));
}
reader.skip(3)?;
let data_size = reader.read_length()?;
let _free_list_offset = reader.read_length()?;
let data_addr = reader.read_addr()?;
reader.seek(data_addr)?;
let data = reader.read_bytes(data_size as usize)?;
Ok(Self { data })
}
pub fn get_string(&self, offset: usize) -> Option<String> {
if offset >= self.data.len() {
return None;
}
let end = self.data[offset..]
.iter()
.position(|&b| b == 0)
.map(|p| offset + p)
.unwrap_or(self.data.len());
Some(String::from_utf8_lossy(&self.data[offset..end]).to_string())
}
}