Merge branch 'fix/p1-attrs-links' into fix/p1-read-gaps

# Conflicts:
#	crates/clawhdf5-format/src/attribute.rs
#	crates/clawhdf5-format/src/group_v1.rs
#	crates/clawhdf5/src/lazy.rs
#	crates/clawhdf5/src/mmap_file.rs
#	docs/known-issues.md
This commit is contained in:
osobh
2026-09-25 22:41:33 -05:00
17 changed files with 1568 additions and 378 deletions
+60 -5
View File
@@ -80,6 +80,53 @@ pub fn find_v1_soft_link(
offset_size: u8,
length_size: u8,
) -> Result<Option<String>, FormatError> {
let mut found = None;
for_each_v1_soft_link(
file_data,
sym_table_msg,
offset_size,
length_size,
|link_name| link_name == name,
|_, target| {
found = Some(target);
false
},
)?;
Ok(found)
}
/// Every soft link in a v1 group, as `(name, target path)`.
pub fn v1_soft_links(
file_data: &[u8],
sym_table_msg: &SymbolTableMessage,
offset_size: u8,
length_size: u8,
) -> Result<Vec<(String, String)>, FormatError> {
let mut links = Vec::new();
for_each_v1_soft_link(
file_data,
sym_table_msg,
offset_size,
length_size,
|_| true,
|name, target| {
links.push((String::from(name), target));
true
},
)?;
Ok(links)
}
/// Visit the soft links of a v1 group whose name passes `wanted`, with their
/// target paths, until `visit` returns false.
fn for_each_v1_soft_link(
file_data: &[u8],
sym_table_msg: &SymbolTableMessage,
offset_size: u8,
length_size: u8,
wanted: impl Fn(&str) -> bool,
mut visit: impl FnMut(&str, String) -> bool,
) -> Result<(), FormatError> {
let heap = LocalHeap::parse(
file_data,
sym_table_msg.local_heap_address as usize,
@@ -103,7 +150,8 @@ pub fn find_v1_soft_link(
heap.validate_free_list(file_data, length_size)?;
heap_checked = true;
}
if heap.read_string(file_data, entry.link_name_offset)? != name {
let name = heap.read_string(file_data, entry.link_name_offset)?;
if !wanted(&name) {
continue;
}
let value_offset = u32::from_le_bytes([
@@ -112,12 +160,19 @@ pub fn find_v1_soft_link(
entry.scratch_pad[2],
entry.scratch_pad[3],
]);
return heap
.read_string(file_data, u64::from(value_offset))
.map(Some);
let target = heap.read_string(file_data, u64::from(value_offset))?;
if !visit(&name, target) {
return Ok(());
}
}
}
Ok(None)
Ok(())
}
/// Whether a v1 symbol-table entry is a soft link (no object header of its
/// own; its target path is in the local heap).
pub fn is_v1_soft_link(entry: &GroupEntry) -> bool {
entry.cache_type == CACHE_TYPE_SOFT_LINK
}
/// Extract the SymbolTableMessage from an object header's messages.