rust_hdf5/format/
symbol_table.rs1use crate::format::superblock::{decode_symbol_table_entry, SymbolTableEntry};
17use crate::format::{FormatError, FormatResult};
18
19pub const SNOD_SIGNATURE: [u8; 4] = *b"SNOD";
21
22#[derive(Debug, Clone)]
24pub struct SymbolTableNode {
25 pub entries: Vec<SymbolTableEntry>,
27}
28
29impl SymbolTableNode {
30 pub fn decode(buf: &[u8], sizeof_addr: usize, sizeof_size: usize) -> FormatResult<Self> {
34 if buf.len() < 8 {
35 return Err(FormatError::BufferTooShort {
36 needed: 8,
37 available: buf.len(),
38 });
39 }
40
41 if buf[0..4] != SNOD_SIGNATURE {
42 return Err(FormatError::InvalidSignature);
43 }
44
45 let version = buf[4];
46 if version != 1 {
47 return Err(FormatError::InvalidVersion(version));
48 }
49
50 let num_symbols = u16::from_le_bytes([buf[6], buf[7]]) as usize;
52
53 let entry_size = sizeof_size + sizeof_addr + 4 + 4 + 16;
55 let needed = 8 + num_symbols * entry_size;
56 if buf.len() < needed {
57 return Err(FormatError::BufferTooShort {
58 needed,
59 available: buf.len(),
60 });
61 }
62
63 let mut pos = 8;
64 let mut entries = Vec::with_capacity(num_symbols);
65
66 for _ in 0..num_symbols {
67 let entry = decode_symbol_table_entry(buf, &mut pos, sizeof_addr, sizeof_size)?;
68 entries.push(entry);
69 }
70
71 Ok(SymbolTableNode { entries })
72 }
73}
74
75#[cfg(test)]
78mod tests {
79 use super::*;
80 use crate::format::UNDEF_ADDR;
81
82 fn build_snod(
83 entries: &[(u64, u64, u32, u64, u64)],
84 sizeof_addr: usize,
85 sizeof_size: usize,
86 ) -> Vec<u8> {
87 let mut buf = Vec::new();
88 buf.extend_from_slice(&SNOD_SIGNATURE);
89 buf.push(1); buf.push(0); buf.extend_from_slice(&(entries.len() as u16).to_le_bytes());
92
93 for &(name_offset, obj_header_addr, cache_type, btree_addr, heap_addr) in entries {
94 buf.extend_from_slice(&name_offset.to_le_bytes()[..sizeof_size]);
96 buf.extend_from_slice(&obj_header_addr.to_le_bytes()[..sizeof_addr]);
98 buf.extend_from_slice(&cache_type.to_le_bytes());
100 buf.extend_from_slice(&0u32.to_le_bytes());
102 if cache_type == 1 {
104 buf.extend_from_slice(&btree_addr.to_le_bytes()[..sizeof_addr]);
105 buf.extend_from_slice(&heap_addr.to_le_bytes()[..sizeof_addr]);
106 let used = 2 * sizeof_addr;
107 if used < 16 {
108 buf.extend_from_slice(&vec![0u8; 16 - used]);
109 }
110 } else {
111 buf.extend_from_slice(&[0u8; 16]);
112 }
113 }
114
115 buf
116 }
117
118 #[test]
119 fn decode_basic() {
120 let snod = build_snod(
121 &[
122 (8, 0x100, 0, UNDEF_ADDR, UNDEF_ADDR), (16, 0x200, 1, 0x300, 0x400), ],
125 8,
126 8,
127 );
128 let node = SymbolTableNode::decode(&snod, 8, 8).unwrap();
129 assert_eq!(node.entries.len(), 2);
130 assert_eq!(node.entries[0].name_offset, 8);
131 assert_eq!(node.entries[0].obj_header_addr, 0x100);
132 assert_eq!(node.entries[0].cache_type, 0);
133 assert_eq!(node.entries[1].cache_type, 1);
134 assert_eq!(node.entries[1].btree_addr, 0x300);
135 assert_eq!(node.entries[1].heap_addr, 0x400);
136 }
137
138 #[test]
139 fn decode_empty() {
140 let snod = build_snod(&[], 8, 8);
141 let node = SymbolTableNode::decode(&snod, 8, 8).unwrap();
142 assert!(node.entries.is_empty());
143 }
144
145 #[test]
146 fn decode_bad_sig() {
147 let mut snod = build_snod(&[], 8, 8);
148 snod[0] = b'X';
149 assert!(matches!(
150 SymbolTableNode::decode(&snod, 8, 8).unwrap_err(),
151 FormatError::InvalidSignature
152 ));
153 }
154
155 #[test]
156 fn decode_bad_version() {
157 let mut snod = build_snod(&[], 8, 8);
158 snod[4] = 2;
159 assert!(matches!(
160 SymbolTableNode::decode(&snod, 8, 8).unwrap_err(),
161 FormatError::InvalidVersion(2)
162 ));
163 }
164
165 #[test]
166 fn decode_too_short() {
167 assert!(matches!(
168 SymbolTableNode::decode(&[0u8; 4], 8, 8).unwrap_err(),
169 FormatError::BufferTooShort { .. }
170 ));
171 }
172
173 #[test]
174 fn decode_4byte() {
175 let snod = build_snod(&[(4, 0x80, 0, UNDEF_ADDR, UNDEF_ADDR)], 4, 4);
176 let node = SymbolTableNode::decode(&snod, 4, 4).unwrap();
177 assert_eq!(node.entries.len(), 1);
178 assert_eq!(node.entries[0].name_offset, 4);
179 assert_eq!(node.entries[0].obj_header_addr, 0x80);
180 }
181}