format: chunk grids with a zero extent have no chunks (no division by zero)
A Fixed or Extensible Array index whose maximum extent (the current one when no maximum is recorded) is 0 along a dimension has a zero stride for every dimension before it; ChunkGrid::offsets divided by it. The unfixed editor made such files by resizing a clawhdf5-written dataset to a zero extent: `h5rs check` panicked and the next resize raised an internal error (12 of the reviewer's random-edit seeds 10..39). Such an index has no slot for any chunk of the dataset; offsets now returns None. Tests: chunk_grid::zero_extent_has_no_chunks; edit_interop's zero_extent_resizes_without_a_recorded_maximum on a file the unfixed editor left (fixture) and on a 2.7.0-written file taken through zero extents with `h5rs check --data` and h5dump at every step; test_edit.py random edits on seeds 10..39 of a clawhdf5-written file. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -135,6 +135,12 @@ impl ChunkGrid {
|
||||
let mut rem = index;
|
||||
for p in 0..rank {
|
||||
let d = self.order[p];
|
||||
// A zero stride: a later dimension has no chunks (its maximum,
|
||||
// or with none recorded its current extent, is 0), so no slot of
|
||||
// the index is a chunk of the dataset.
|
||||
if self.down[p] == 0 {
|
||||
return None;
|
||||
}
|
||||
let scaled = rem / self.down[p];
|
||||
rem %= self.down[p];
|
||||
if scaled >= self.cur_chunks[d] {
|
||||
@@ -193,6 +199,28 @@ mod tests {
|
||||
assert_eq!(g.offsets(11), Some(vec![2, 3]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_extent_has_no_chunks() {
|
||||
// No maximum recorded and a zero current dimension: every stride
|
||||
// before it is 0 (this divided by zero).
|
||||
let g = ChunkGrid::fixed_array(&[1, 0], None, &[6, 6]).unwrap();
|
||||
for i in 0..16 {
|
||||
assert_eq!(g.offsets(i), None);
|
||||
}
|
||||
let g = ChunkGrid::fixed_array(&[0, 0, 3], Some(&[4, 0, 3]), &[2, 2, 3]).unwrap();
|
||||
for i in 0..16 {
|
||||
assert_eq!(g.offsets(i), None);
|
||||
}
|
||||
let g = ChunkGrid::extensible_array(&[0, 5], Some(&[u64::MAX, 0]), &[2, 2]).unwrap();
|
||||
for i in 0..16 {
|
||||
assert_eq!(g.offsets(i), None);
|
||||
}
|
||||
// A zero last dimension leaves the other strides alone.
|
||||
let g = ChunkGrid::fixed_array(&[4, 0], Some(&[4, 6]), &[2, 3]).unwrap();
|
||||
assert_eq!(g.offsets(0), None);
|
||||
assert_eq!(g.linear_index(&[1, 1]), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_two_unlimited_dims_after_the_first() {
|
||||
assert!(ChunkGrid::fixed_array(&[4, 6], Some(&[u64::MAX, u64::MAX]), &[2, 3]).is_err());
|
||||
|
||||
Reference in New Issue
Block a user