async_hdf5/messages/dataspace.rs
1use bytes::Bytes;
2
3use crate::endian::HDF5Reader;
4use crate::error::Result;
5
6/// Dataspace message — describes the dimensionality of a dataset.
7///
8/// Message type 0x0001.
9#[derive(Debug, Clone)]
10pub struct DataspaceMessage {
11 /// Number of dimensions (0 = scalar).
12 pub rank: u8,
13 /// Dataspace type: 0 = scalar, 1 = simple, 2 = null.
14 /// Only present for v2 messages; v1 defaults to 1 (simple) for rank > 0,
15 /// 0 (scalar) for rank == 0.
16 pub dataspace_type: u8,
17 /// Current size along each dimension.
18 pub dimensions: Vec<u64>,
19 /// Maximum size along each dimension (None = same as current).
20 /// A value of u64::MAX means unlimited.
21 pub max_dimensions: Option<Vec<u64>>,
22}
23
24impl DataspaceMessage {
25 /// Parse from the raw message bytes.
26 pub fn parse(data: &Bytes, size_of_lengths: u8) -> Result<Self> {
27 let mut r = HDF5Reader::with_sizes(data.clone(), 8, size_of_lengths);
28
29 let version = r.read_u8()?;
30 let rank = r.read_u8()?;
31 let flags = r.read_u8()?;
32
33 // v1: reserved (1 byte) + reserved (4 bytes) = 5 bytes (no type field)
34 // v2: type field (1 byte): 0=scalar, 1=simple, 2=null
35 let dataspace_type = match version {
36 1 => {
37 r.skip(5); // 1 reserved + 4 reserved
38 if rank == 0 {
39 0
40 } else {
41 1
42 }
43 }
44 2 => r.read_u8()?,
45 _ => {
46 // Best-effort: try to continue
47
48 r.read_u8()?
49 }
50 };
51
52 let mut dimensions = Vec::with_capacity(rank as usize);
53 for _ in 0..rank {
54 dimensions.push(r.read_length()?);
55 }
56
57 let has_max = flags & 0x01 != 0;
58 let max_dimensions = if has_max {
59 let mut max = Vec::with_capacity(rank as usize);
60 for _ in 0..rank {
61 max.push(r.read_length()?);
62 }
63 Some(max)
64 } else {
65 None
66 };
67
68 Ok(Self {
69 rank,
70 dataspace_type,
71 dimensions,
72 max_dimensions,
73 })
74 }
75}