use crate::{Result, error::Error};
#[derive(Debug, Clone, serde::Serialize)]
pub struct BlobHeap<'a> {
#[serde(skip_serializing)]
data: &'a [u8],
}
impl<'a> BlobHeap<'a> {
#[must_use]
pub fn new(data: &'a [u8]) -> Self {
Self { data }
}
pub fn get(&self, index: usize) -> Result<Vec<u8>> {
Ok(self.get_ref(index)?.to_vec())
}
pub fn get_ref(&self, index: usize) -> Result<&'a [u8]> {
if index >= self.data.len() {
return Err(Error::BlobHeapReadOutOfBound(index, self.data.len()));
}
let header_end = index.saturating_add(4).min(self.data.len());
let (data_length, length_size) =
crate::utils::read_compressed_usize(&self.data[index..header_end])?;
let payload_start = index
.checked_add(length_size)
.ok_or(Error::BlobHeapReadOutOfBound(index, self.data.len()))?;
let payload_end = payload_start
.checked_add(data_length)
.ok_or(Error::BlobHeapReadOutOfBound(index, self.data.len()))?;
if payload_end > self.data.len() {
return Err(Error::BlobHeapReadOutOfBound(payload_end, self.data.len()));
}
Ok(&self.data[payload_start..payload_end])
}
}
impl<'a> crate::DnPe<'a> {
pub fn new_blob_heap(
&self,
_metadata_rva: &u32,
_stream_offset: &u32,
_stream_size: &usize,
_stream_name: &str,
stream_data: &'a [u8],
) -> Result<super::Stream<'a>> {
Ok(super::Stream::BlobHeap(BlobHeap::new(stream_data)))
}
}