fix(format): decode the version-1 VDS mapping list HDF5 2.0 writes
With a 2.0 low version bound, libhdf5 stores the VDS mapping list as heap
block version 1: every entry starts with a flags byte (0x04 same file, no
file name; 0x01/0x02 file/dataset name shared with an earlier entry, whose
index is stored in place of the name). The parser treated only a leading
0x04 byte as special, so a 0x00 flags byte read as an empty (same-file)
name and shared names were read as garbage.
Decode it as H5D__virtual_load_layout does, refusing unknown flags,
forward references and block versions above 1.
Test: vds_interop::vds_mapping_block_version1_shared_names (h5py
libver=("v200","v200") with repeated long names; failed before with
"unknown dataspace selection type") plus the exact heap block as a unit
test.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -154,3 +154,39 @@ expect("v1.h5", "grid", "grid")
|
||||
assert_matches_libhdf5(dir.path(), "v1.h5", "strided", "strided");
|
||||
assert_matches_libhdf5(dir.path(), "v1.h5", "grid", "grid");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mapping list encoding
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// With a 2.0 low version bound libhdf5 writes the mapping list as block
|
||||
/// version 1: a flags byte per entry, and repeated names stored as the index
|
||||
/// of the entry that first spelled them out. The flags byte was mistaken for
|
||||
/// an empty (same-file) name.
|
||||
#[test]
|
||||
fn vds_mapping_block_version1_shared_names() {
|
||||
skip_if_no_python!();
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
generate(
|
||||
dir.path(),
|
||||
r#"
|
||||
name = "a_rather_long_dataset_name"
|
||||
with h5py.File("a_rather_long_source_file.h5", "w") as s:
|
||||
s.create_dataset(name, data=np.arange(12.0) + 100)
|
||||
with h5py.File("shared.h5", "w", libver=("v200", "v200")) as f:
|
||||
f.create_dataset(name, data=np.arange(12.0) * -1)
|
||||
lay = h5py.VirtualLayout(shape=(4, 4), dtype="f8")
|
||||
for i in range(3):
|
||||
src = h5py.VirtualSource("a_rather_long_source_file.h5", name, shape=(12,))
|
||||
lay[i] = src[4 * i:4 * i + 4]
|
||||
lay[3] = h5py.VirtualSource(".", name, shape=(12,))[0:4]
|
||||
f.create_virtual_dataset("v", lay)
|
||||
# the heap block must really be version 1 for this test to mean anything
|
||||
raw = open("shared.h5", "rb").read()
|
||||
gcol = raw.index(b"GCOL")
|
||||
assert raw[gcol + 32] == 1, "expected a version-1 VDS mapping block"
|
||||
expect("shared.h5", "v", "shared")
|
||||
"#,
|
||||
);
|
||||
assert_matches_libhdf5(dir.path(), "shared.h5", "v", "shared");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user