Skip to main content

hdf5_reader/messages/
external_files.rs

1//! HDF5 External Data Files message (type 0x0007).
2//!
3//! Indicates that raw data for a dataset is stored in one or more external
4//! files. Rarely used in practice, especially in NetCDF files.
5
6use crate::error::Result;
7use crate::io::Cursor;
8
9/// A single external file slot.
10#[derive(Debug, Clone)]
11pub struct ExternalFileSlot {
12    /// Offset into the local heap for the file name.
13    pub name_offset: u64,
14    /// Byte offset into the external file where data starts.
15    pub offset: u64,
16    /// Number of bytes to read from the external file.
17    pub size: u64,
18}
19
20/// Parsed external data files message.
21#[derive(Debug, Clone)]
22pub struct ExternalFilesMessage {
23    /// Address of the local heap containing file names.
24    pub heap_address: u64,
25    /// List of external file slots.
26    pub slots: Vec<ExternalFileSlot>,
27}
28
29/// Parse an external data files message.
30pub fn parse(
31    cursor: &mut Cursor<'_>,
32    offset_size: u8,
33    length_size: u8,
34    msg_size: usize,
35) -> Result<ExternalFilesMessage> {
36    let start = cursor.position();
37
38    let _version = cursor.read_u8()?;
39    let _reserved = cursor.read_bytes(3)?;
40
41    // Allocated slots (for pre-allocation; may differ from used slots)
42    let _allocated_slots = cursor.read_u16_le()?;
43    // Used slots — actual number of entries
44    let used_slots = cursor.read_u16_le()? as usize;
45
46    let heap_address = cursor.read_offset(offset_size)?;
47
48    let mut slots = Vec::with_capacity(used_slots);
49    for _ in 0..used_slots {
50        let name_offset = cursor.read_length(length_size)?;
51        let offset = cursor.read_length(length_size)?;
52        let size = cursor.read_length(length_size)?;
53        slots.push(ExternalFileSlot {
54            name_offset,
55            offset,
56            size,
57        });
58    }
59
60    let consumed = (cursor.position() - start) as usize;
61    if consumed < msg_size {
62        cursor.skip(msg_size - consumed)?;
63    }
64
65    Ok(ExternalFilesMessage {
66        heap_address,
67        slots,
68    })
69}