Read HDF5 1.6-era files, user blocks, VDS, dense attributes and large groups #13
@@ -831,6 +831,16 @@ impl<'a, 'r> Sources<'a, 'r> {
|
|||||||
path: &str,
|
path: &str,
|
||||||
datatype: &Datatype,
|
datatype: &Datatype,
|
||||||
) -> Result<Option<SourceData>, FormatError> {
|
) -> Result<Option<SourceData>, FormatError> {
|
||||||
|
// Variable-length and reference elements are addresses into the file
|
||||||
|
// that holds them (global-heap IDs, object addresses). Copied out of
|
||||||
|
// another file they would be decoded against the virtual dataset's
|
||||||
|
// file and name some other object, so refuse rather than return them.
|
||||||
|
if file != "." && holds_file_addresses(datatype) {
|
||||||
|
return Err(vds_err(format!(
|
||||||
|
"VDS source {path} in {file}: variable-length and reference data \
|
||||||
|
from another file is not supported"
|
||||||
|
)));
|
||||||
|
}
|
||||||
let Some(bytes) = self.file(file)? else {
|
let Some(bytes) = self.file(file)? else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
@@ -841,6 +851,21 @@ impl<'a, 'r> Sources<'a, 'r> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether elements of `dt` contain addresses into their own file:
|
||||||
|
/// variable-length data (global-heap IDs) or references.
|
||||||
|
fn holds_file_addresses(dt: &Datatype) -> bool {
|
||||||
|
match dt {
|
||||||
|
Datatype::VariableLength { .. } | Datatype::Reference { .. } => true,
|
||||||
|
Datatype::Compound { members, .. } => {
|
||||||
|
members.iter().any(|m| holds_file_addresses(&m.datatype))
|
||||||
|
}
|
||||||
|
Datatype::Array { base_type, .. } | Datatype::Enumeration { base_type, .. } => {
|
||||||
|
holds_file_addresses(base_type)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An opened source dataset's object header.
|
/// An opened source dataset's object header.
|
||||||
struct OpenSource {
|
struct OpenSource {
|
||||||
offset_size: u8,
|
offset_size: u8,
|
||||||
|
|||||||
@@ -290,6 +290,44 @@ expect("nested.h5", "v", "nested")
|
|||||||
assert_matches_libhdf5(dir.path(), "nested.h5", "v", "nested");
|
assert_matches_libhdf5(dir.path(), "nested.h5", "v", "nested");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Variable-length and reference elements are addresses into their own file.
|
||||||
|
/// Copied raw from an external source they would be decoded against the
|
||||||
|
/// virtual dataset's file and name another object, so they are refused.
|
||||||
|
#[test]
|
||||||
|
fn vds_external_variable_length_source_is_an_error_not_foreign_addresses() {
|
||||||
|
skip_if_no_python!();
|
||||||
|
let dir = tempfile::tempdir().unwrap();
|
||||||
|
generate(
|
||||||
|
dir.path(),
|
||||||
|
r#"
|
||||||
|
st = h5py.string_dtype()
|
||||||
|
with h5py.File("src.h5", "w") as s:
|
||||||
|
s.create_dataset("names", data=np.array(["alpha", "beta", "gamma"], dtype=object), dtype=st)
|
||||||
|
s.create_dataset("refs", data=[s.ref, s.ref], dtype=h5py.ref_dtype)
|
||||||
|
with h5py.File("v.h5", "w", libver="latest") as f:
|
||||||
|
f.create_dataset("pad", data=np.arange(64.0))
|
||||||
|
lay = h5py.VirtualLayout(shape=(3,), dtype=st)
|
||||||
|
lay[:] = h5py.VirtualSource("src.h5", "names", shape=(3,))
|
||||||
|
f.create_virtual_dataset("names", lay)
|
||||||
|
lay = h5py.VirtualLayout(shape=(2,), dtype=h5py.ref_dtype)
|
||||||
|
lay[:] = h5py.VirtualSource("src.h5", "refs", shape=(2,))
|
||||||
|
f.create_virtual_dataset("refs", lay)
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
let f = File::open(dir.path().join("v.h5")).unwrap();
|
||||||
|
for name in ["names", "refs"] {
|
||||||
|
let err = f
|
||||||
|
.dataset(name)
|
||||||
|
.unwrap()
|
||||||
|
.read_selection(&clawhdf5_format::selection::Selection::All)
|
||||||
|
.expect_err("raw addresses from another file must not be returned");
|
||||||
|
assert!(
|
||||||
|
err.to_string().contains("from another file"),
|
||||||
|
"{name}: unexpected error: {err}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Unlimited and printf-style mappings
|
// Unlimited and printf-style mappings
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user