///|
/// The two addresses stored in a symbol table message.
priv struct SymbolTableInfo {
btree_address : UInt64
heap_address : UInt64
}
///|
fn parse_symbol_table_message(
message : HeaderMessage,
offset_size : Int32,
_length_size : Int32,
) -> SymbolTableInfo raise Hdf5Error {
guard message.msg_type == msg_symbol_table else {
raise InvalidField("message is not a symbol table message")
}
let reader = Reader::new(message.data)
let btree_address = reader.read_uint_le(offset_size)
let heap_address = reader.read_uint_le(offset_size)
{ btree_address, heap_address, }
}
///|
/// A hard or soft link found in a version 1 group.
priv struct GroupLink {
name : String
object_header_address : UInt64
cache_type : UInt32
link_target : String?
external_path : String?
}
///|
fn read_symbol_table_node(
bytes : Bytes,
address : UInt64,
offset_size : Int32,
_length_size : Int32,
base_address : UInt64,
heap : LocalHeap,
links : Array[GroupLink],
) -> Unit raise Hdf5Error {
let absolute = address_to_offset(address, base_address)
let reader = Reader::at(bytes, absolute)
let signature = reader.read_bytes(4)
guard signature == b"SNOD" else {
raise InvalidField("expected SNOD signature")
}
let version = reader.read_u8().to_int()
guard version == 1 else {
raise InvalidField("unsupported symbol table node version")
}
reader.skip(1)
let symbol_count = reader.read_u16_le().to_int()
for _ in 0.. Unit raise Hdf5Error {
let absolute = address_to_offset(address, base_address)
guard !visited.contains(absolute) else { return }
visited.push(absolute)
let reader = Reader::at(bytes, absolute)
let signature = reader.read_bytes(4)
guard signature == b"TREE" else {
raise InvalidField("expected TREE signature")
}
let node_type = reader.read_u8().to_int()
guard node_type == 0 else {
raise InvalidField("B-tree node is not a group node")
}
let node_level = reader.read_u8().to_int()
if expected_level >= 0 {
guard node_level == expected_level else {
raise InvalidField("unexpected B-tree level")
}
}
let entries_used = reader.read_u16_le().to_int()
let _left_sibling = reader.read_uint_le(offset_size)
let _right_sibling = reader.read_uint_le(offset_size)
for _ in 0.. 0 {
read_group_btree_node(
bytes,
child,
node_level - 1,
offset_size,
length_size,
base_address,
heap,
links,
visited,
)
} else {
read_symbol_table_node(
bytes, child, offset_size, length_size, base_address, heap, links,
)
}
}
let _final_key = reader.read_uint_le(length_size)
}
///|
/// Reads all links from a version 1 group (symbol table message).
fn read_group_links_v1(
bytes : Bytes,
btree_address : UInt64,
heap_address : UInt64,
offset_size : Int32,
length_size : Int32,
base_address : UInt64,
) -> Array[GroupLink] raise Hdf5Error {
let heap = parse_local_heap(
bytes, heap_address, offset_size, length_size, base_address,
)
let links : Array[GroupLink] = []
let visited : Array[Int32] = []
read_group_btree_node(
bytes, btree_address, -1, offset_size, length_size, base_address, heap, links,
visited,
)
links
}