fix(format): read enum and bool datasets through their base integer type

read_i64/read_u64/read_i32/read_f64/read_f32 refused enumeration
datatypes, including h5py's bool (an enum of int8), with a type
mismatch. Read them as their base type's integer values, the way array
datatypes already read through theirs.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-25 21:08:37 -05:00
co-authored by Claude Opus 5.5
parent 417c9516ca
commit c8c2930fc0
2 changed files with 53 additions and 7 deletions
@@ -273,3 +273,41 @@ with h5py.File("{path}", "r") as f:
assert_eq!(got32, want32, "{name} as f32");
}
}
#[test]
fn enum_and_bool_datasets_read_as_their_integer_values() {
// Enumerations (h5py stores bool as an enum of int8) were refused by the
// numeric readers with a type mismatch.
skip_if_no_python!();
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("enums.h5");
let script = format!(
r#"{PRELUDE}
with h5py.File("{path}", "w") as f:
f.create_dataset("bool", data=np.array([True, False, True]))
e = h5py.enum_dtype({{"RED": 0, "GREEN": 7, "BLUE": -3}}, basetype=">i2")
f.create_dataset("enum_i2be", data=np.array([0, 7, -3, 7], ">i2"), dtype=e)
e = h5py.enum_dtype({{"LOW": 0, "HIGH": 200}}, basetype="u1")
f.create_dataset("enum_u1", data=np.array([200, 0, 200], "u1"), dtype=e)
e = h5py.enum_dtype({{"A": -(2**40), "B": 2**40}}, basetype="<i8")
f.create_dataset("enum_i8", data=np.array([2**40, -(2**40)], "<i8"), dtype=e)
with h5py.File("{path}", "r") as f:
for name in ("bool", "enum_i2be", "enum_u1", "enum_i8"):
emit(name, np.asarray(f[name][()]).astype(np.int64))
"#,
path = path.display()
);
let expected = run_python(&script);
let file = File::open(&path).unwrap();
for name in ["bool", "enum_i2be", "enum_u1", "enum_i8"] {
let ds = file.dataset(name).unwrap();
let want: Vec<i64> = parse(&expected[name]);
assert_eq!(ds.read_i64().unwrap(), want, "{name} as i64");
let want_f64: Vec<f64> = want.iter().map(|&v| v as f64).collect();
assert_eq!(ds.read_f64().unwrap(), want_f64, "{name} as f64");
}
let bools = file.dataset("bool").unwrap();
assert_eq!(bools.read_u64().unwrap(), vec![1, 0, 1]);
assert_eq!(bools.read_i32().unwrap(), vec![1, 0, 1]);
}