Skip to main content

hdf5_reader/messages/
shared.rs

1//! HDF5 Shared Message (Phase 2 stub).
2//!
3//! A shared message indicates that the actual message content is stored
4//! elsewhere — either in another object header or in the shared message
5//! heap (SOHM).
6
7use crate::error::{Error, Result};
8use crate::io::Cursor;
9
10/// Where the shared message is stored.
11#[derive(Debug, Clone)]
12pub enum SharedMessage {
13    /// Shared in another object header at the given address.
14    SharedInOhdr { address: u64 },
15    /// Shared in the SOHM fractal heap, identified by a heap ID.
16    SharedInSohm { heap_id: Vec<u8> },
17}
18
19/// Parse a shared message wrapper.
20///
21/// The `type_field` indicates how the message is shared:
22/// - 0 or 2: shared in another object header (version-dependent)
23/// - 1 or 3: shared in the SOHM
24pub fn parse(
25    cursor: &mut Cursor<'_>,
26    offset_size: u8,
27    _length_size: u8,
28    msg_size: usize,
29) -> Result<SharedMessage> {
30    let start = cursor.position();
31    let version = cursor.read_u8()?;
32
33    let msg = match version {
34        1 => {
35            // Version 1: type byte + reserved(6) + address
36            let _type_field = cursor.read_u8()?;
37            let _reserved = cursor.read_bytes(6)?;
38            let address = cursor.read_offset(offset_size)?;
39            SharedMessage::SharedInOhdr { address }
40        }
41        2 | 3 => {
42            let type_field = cursor.read_u8()?;
43            match type_field {
44                0 | 2 => {
45                    // Shared in another object header
46                    let address = cursor.read_offset(offset_size)?;
47                    SharedMessage::SharedInOhdr { address }
48                }
49                1 | 3 => {
50                    // Shared in SOHM heap — heap ID is 8 bytes
51                    let heap_id = cursor.read_bytes(8)?.to_vec();
52                    SharedMessage::SharedInSohm { heap_id }
53                }
54                t => {
55                    return Err(Error::InvalidData(format!(
56                        "unknown shared message type: {}",
57                        t
58                    )));
59                }
60            }
61        }
62        v => {
63            return Err(Error::InvalidData(format!(
64                "unsupported shared message version: {}",
65                v
66            )));
67        }
68    };
69
70    let consumed = (cursor.position() - start) as usize;
71    if consumed < msg_size {
72        cursor.skip(msg_size - consumed)?;
73    }
74
75    Ok(msg)
76}