rustyhdf5_format/
group_info.rs1use crate::error::FormatError;
4
5#[derive(Debug, Clone, PartialEq)]
7pub struct GroupInfoMessage {
8 pub max_compact: Option<u16>,
10 pub min_dense: Option<u16>,
12 pub estimated_num_entries: Option<u16>,
14 pub estimated_name_length: Option<u16>,
16}
17
18impl GroupInfoMessage {
19 pub fn parse(data: &[u8]) -> Result<GroupInfoMessage, FormatError> {
21 if data.len() < 2 {
22 return Err(FormatError::UnexpectedEof {
23 expected: 2,
24 available: data.len(),
25 });
26 }
27
28 let version = data[0];
29 if version != 0 {
30 return Err(FormatError::InvalidGroupInfoVersion(version));
31 }
32
33 let flags = data[1];
34 let has_link_phase = flags & 0x01 != 0;
35 let has_estimated = flags & 0x02 != 0;
36
37 let mut pos = 2;
38
39 let (max_compact, min_dense) = if has_link_phase {
40 if pos + 4 > data.len() {
41 return Err(FormatError::UnexpectedEof {
42 expected: pos + 4,
43 available: data.len(),
44 });
45 }
46 let mc = u16::from_le_bytes([data[pos], data[pos + 1]]);
47 let md = u16::from_le_bytes([data[pos + 2], data[pos + 3]]);
48 pos += 4;
49 (Some(mc), Some(md))
50 } else {
51 (None, None)
52 };
53
54 let (estimated_num_entries, estimated_name_length) = if has_estimated {
55 if pos + 4 > data.len() {
56 return Err(FormatError::UnexpectedEof {
57 expected: pos + 4,
58 available: data.len(),
59 });
60 }
61 let ne = u16::from_le_bytes([data[pos], data[pos + 1]]);
62 let nl = u16::from_le_bytes([data[pos + 2], data[pos + 3]]);
63 (Some(ne), Some(nl))
64 } else {
65 (None, None)
66 };
67
68 Ok(GroupInfoMessage {
69 max_compact,
70 min_dense,
71 estimated_num_entries,
72 estimated_name_length,
73 })
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn with_link_phase_change() {
83 let data = vec![0, 0x01, 8, 0, 6, 0]; let msg = GroupInfoMessage::parse(&data).unwrap();
85 assert_eq!(msg.max_compact, Some(8));
86 assert_eq!(msg.min_dense, Some(6));
87 assert_eq!(msg.estimated_num_entries, None);
88 }
89
90 #[test]
91 fn with_estimated_entry_info() {
92 let data = vec![0, 0x02, 4, 0, 16, 0]; let msg = GroupInfoMessage::parse(&data).unwrap();
94 assert_eq!(msg.max_compact, None);
95 assert_eq!(msg.estimated_num_entries, Some(4));
96 assert_eq!(msg.estimated_name_length, Some(16));
97 }
98
99 #[test]
100 fn both_flags_set() {
101 let data = vec![0, 0x03, 8, 0, 6, 0, 10, 0, 32, 0];
102 let msg = GroupInfoMessage::parse(&data).unwrap();
103 assert_eq!(msg.max_compact, Some(8));
104 assert_eq!(msg.min_dense, Some(6));
105 assert_eq!(msg.estimated_num_entries, Some(10));
106 assert_eq!(msg.estimated_name_length, Some(32));
107 }
108
109 #[test]
110 fn no_flags() {
111 let data = vec![0, 0x00];
112 let msg = GroupInfoMessage::parse(&data).unwrap();
113 assert_eq!(msg.max_compact, None);
114 assert_eq!(msg.min_dense, None);
115 assert_eq!(msg.estimated_num_entries, None);
116 assert_eq!(msg.estimated_name_length, None);
117 }
118
119 #[test]
120 fn invalid_version() {
121 let data = vec![1, 0];
122 let err = GroupInfoMessage::parse(&data).unwrap_err();
123 assert_eq!(err, FormatError::InvalidGroupInfoVersion(1));
124 }
125}