Skip to content

zarr3: support the regular_bounded chunk grid - #296

Draft
rhoadesScholar wants to merge 7 commits into
google:masterfrom
rhoadesScholar:zarr3-offset-chunk-key-encoding
Draft

rhoadesScholar wants to merge 7 commits into
google:masterfrom
rhoadesScholar:zarr3-offset-chunk-key-encoding

Conversation

@rhoadesScholar

@rhoadesScholar rhoadesScholar commented Oct 15, 2026 •

Copy link
Copy Markdown

Prototype for zarr-developers/zarr-extensions#79: the regular_bounded chunk grid proposed in zarr-developers/zarr-extensions#81. It is a regular grid with an origin (the array coordinate where chunk 0 starts) and a lower_bound (the coordinate of the first element), following the origin-and-bounds design suggested on zarr-developers/zarr-extensions#80.

  • Domain and grid. The domain starts at lower_bound, and the internal grid space is the array coordinate minus origin. Cell indices are therefore the absolute chunk grid indices, negative where they should be, and they stay put when the lower bound moves.
  • Resize. The lower bound of a regular_bounded array is implicit, so Resize can grow or shrink it. Chunks that fall off the front are deleted through the existing box-difference path. regular arrays are unchanged.
  • Keys. Parsing accepts a leading - and rejects -0. Formatting needed no change.
  • Fill value. The per-component fill value is broadcast over an unbounded domain. It previously started at 0, which AsyncWriteArray::Spec::GetFillValueForDomain asserts on once chunks sit at negative internal coordinates.
  • Layout and compatibility. The chunk layout reports origin as the grid origin. The compatibility key ignores lower_bound, as it ignores shape.
  • Also applies the rank-0 prefix fix to ParseKey from review.

Before and after. Before, Open refuses such an array because the chunk grid is unknown. After:

  • GrowsInFrontByEditingZarrJsonAlone writes a regular array, rewrites only zarr.json to grow it by two elements in front (less than a chunk), and reopens it with domain [-2, 6). It reads the old data at its old coordinates, then writes the front without any existing chunk moving.
  • ResizeMovesTheLowerBound grows the front through tensorstore::Resize, shrinks it again, and checks that exactly the chunks that fell off are deleted.

Also checked by hand: two stores written by zarr-python (zarr-developers/zarr-python#4516) read here with the same domains and values. One was grown in front by prepend; the other has a non-zero origin on both axes.

Tests. The metadata tests cover the round trip, members rejected under regular, both members required with one entry per dimension, and the compatibility key. The driver tests cover the domain and grid origin, keys, reopening, growth by a metadata edit, resizing the lower bound both ways, storage statistics over negative keys, and -0. bazel test //tensorstore/driver/zarr3/... passes.

Not covered here: creating a regular_bounded array from a schema domain with a non-zero origin. Today such a domain is refused; it could map onto this grid.

@google-cla

google-cla Bot commented Oct 15, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for the 'offset' chunk key encoding in the Zarr3 driver, allowing arrays to grow in the negative direction of a dimension by applying a fixed per-dimension integer offset to chunk grid positions. The changes include metadata parsing, validation, key formatting/parsing logic, schema updates, and comprehensive unit tests. The review feedback highlights two issues in driver.cc: first, a potential out-of-bounds or undefined behavior when parsing keys for rank 0 arrays due to incorrect prefix removal length; second, a potential issue in MinGridIndexForLexicographicalOrder where passing a non-positive value to MinValueWithMaxBase10Digits can be avoided by returning -offset directly when the interval consists entirely of negative keys.

Comment thread tensorstore/driver/zarr3/driver.cc Outdated
Comment thread tensorstore/driver/zarr3/driver.cc Outdated
The `offset` encoding stores a chunk under the `default` key of its grid
index plus a fixed per-dimension integer offset, so that an array grows
in the negative direction of a dimension by whole chunks as a
metadata-only change (zarr-extensions chunk-key-encodings/offset).

Adds the kind to `ChunkKeyEncoding` with its `offset` vector (required
for this kind, rejected for the others, length checked against the rank
in ValidateMetadata), applies it in FormatKey and GetChunkStorageKey, and
accepts a leading `-` in ParseKey. MinGridIndexForLexicographicalOrder
splits off every grid index whose key is negative, since negative base-10
components do not sort numerically, and shifts the digit-count rule for
the rest. Schema docs and tests, including a growth that rewrites only
zarr.json and a shrink that deletes through key ranges.
@rhoadesScholar
rhoadesScholar force-pushed the zarr3-offset-chunk-key-encoding branch from e713ac2 to 92e1fec Compare October 15, 2026 23:18
@rhoadesScholar
rhoadesScholar marked this pull request as ready for review October 16, 2026 00:13
@rhoadesScholar

Copy link
Copy Markdown
Author

Ready for review. The encoding is proposed in zarr-developers/zarr-extensions#80; this is the reader side. cc @jbms

@rhoadesScholar
rhoadesScholar marked this pull request as draft October 16, 2026 19:48
@rhoadesScholar

Copy link
Copy Markdown
Author

Converting to draft while the design is worked out in zarr-developers/zarr-extensions#79. This branch is a prototype and will be reworked to match.

…y encoding

Rework following zarr-extensions#79. The `offset` chunk key encoding is
removed. `regular_bounded` is a regular chunk grid with an `origin` (the
array coordinate where chunk 0 starts) and a `lower_bound` (the
coordinate of the first element).

The array's domain starts at `lower_bound`, and the internal grid space
is the array coordinate minus `origin`, so chunk grid indices are the
absolute ones and may be negative. The lower bound of a
`regular_bounded` array is implicit, so `Resize` can move it; chunks
that fall off the front are deleted through the existing box-difference
path. `regular` arrays are unchanged.

Key parsing accepts a leading `-` and rejects `-0`. The per-component
fill value is broadcast over an unbounded domain, since chunks may now
sit at negative internal coordinates. The chunk layout reports `origin`
as the grid origin, and the compatibility key ignores `lower_bound`, as
it ignores `shape`.
@rhoadesScholar rhoadesScholar changed the title zarr3: support the offset chunk key encoding zarr3: support the regular_bounded chunk grid Oct 16, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant