1use std::sync::Arc;
2
3use bytes::Bytes;
4
5use crate::endian::HDF5Reader;
6use crate::error::{HDF5Error, Result};
7use crate::reader::AsyncFileReader;
8
9#[derive(Debug, Clone)]
22pub struct LocalHeap {
23 data_segment: Bytes,
25}
26
27impl LocalHeap {
28 pub async fn read(
30 reader: &Arc<dyn AsyncFileReader>,
31 address: u64,
32 size_of_offsets: u8,
33 size_of_lengths: u8,
34 ) -> Result<Self> {
35 let header_size = 8 + 2 * size_of_lengths as u64 + size_of_offsets as u64;
37 let header_data = reader.get_bytes(address..address + header_size).await?;
38
39 let mut r = HDF5Reader::with_sizes(header_data, size_of_offsets, size_of_lengths);
40
41 let sig = r.read_bytes(4)?;
43 if &sig != b"HEAP" {
44 return Err(HDF5Error::InvalidHeapSignature {
45 expected: "HEAP".into(),
46 got: String::from_utf8_lossy(&sig).into(),
47 });
48 }
49
50 let version = r.read_u8()?;
51 if version != 0 {
52 return Err(HDF5Error::UnsupportedHeapVersion(version));
53 }
54 r.skip(3); let data_segment_size = r.read_length()?;
57 let _free_list_offset = r.read_length()?;
58 let data_segment_address = r.read_offset()?;
59
60 let data_segment = reader
62 .get_bytes(data_segment_address..data_segment_address + data_segment_size)
63 .await?;
64
65 Ok(Self { data_segment })
66 }
67
68 pub fn get_string(&self, offset: u64) -> Result<String> {
70 let start = offset as usize;
71 if start >= self.data_segment.len() {
72 return Err(HDF5Error::UnexpectedEof {
73 needed: start + 1,
74 available: self.data_segment.len(),
75 });
76 }
77
78 let bytes = &self.data_segment[start..];
79 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
80
81 Ok(String::from_utf8_lossy(&bytes[..end]).into())
82 }
83}