Skip to content

gamut-metadata: settle one shape for the format crates' typed accessors (blocks fallible or not, and whose error) #628

Description

@justin13888

The inconsistency

Four crates now expose the facade's typed models, and they do not agree on the shape:

crate blocks() metadata()
gamut-jpeg Vec<MetadataBlock<'_>> gamut_metadata::Result<Metadata>
gamut-jxl Vec<MetadataBlock<'_>> gamut_metadata::Result<Metadata>
gamut-dng Vec<MetadataBlock<'_>> (none — DngMetadata holds the facade's Exif by value)
gamut-heic Result<Vec<MetadataBlock<'_>>> (the crate's error) Result<Metadata> (the crate's error)

So a caller writing format-agnostic code over blocks() cannot: three of the four are infallible
and one is not, and the fallible one reports gamut_heic::Error while the others report
gamut_metadata::MetadataError.

The divergence is not arbitrary. HEIC's payloads are items in an ISOBMFF tree, and resolving an
item to its bytes can fail (a missing iloc extent, an item construction method the crate does not
support), so blocks() there is genuinely a fallible operation. JPEG, JXL and DNG have already
resolved their payloads to owned or borrowed bytes by the time the type exists, so nothing can fail.

What needs deciding

  1. Is blocks() fallible everywhere, or infallible everywhere? Making it uniformly fallible
    costs three crates a ? for an error they can never return. Making it uniformly infallible
    forces HEIC either to resolve items eagerly at parse time or to drop the ones it cannot resolve,
    which is a silent loss the workspace generally refuses.
  2. Whose error type? A crate-native error keeps the crate self-contained; the facade's error
    makes the accessor usable through a trait. Today's answer differs per crate by accident rather
    than by rule.
  3. Should this be a trait at all? A TypedMetadata trait in gamut-metadata would fix both
    answers by construction and let a caller write one function over every wired format — but it
    also fixes them for every crate wired later, so it is worth choosing on purpose. It must stay
    object-safe and C-portable per AGENTS.md.

This outlives any one pull request: it binds gamut-png, gamut-webp, gamut-avif and
gamut-tiff when they are wired (tracked by the #420 remainder).

Evidence

Refs #420.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions