Skip to content

gamut-iptc: an extension field the projection cannot express reads as absent — should the model widen? #609

Description

@justin13888

gamut_iptc::extension now decides retention by round-trippability: a field enters the typed
value only when the property the writer will emit for that value reproduces the field that was read
— value, RDF container kind, qualifiers and all. Everything else is kept verbatim in the type's
other list (PR #540, round 4). Nothing is lost from the graph any more.

The cost is on the read side. A field the projection cannot express now reads as None (or an
empty Vec) where it previously returned a value the writer would then have destroyed. The module
enumerates the shapes; the ones a real file is most likely to carry are:

  • a URL held as rdf:resource rather than as element text — Iptc4xmpCore:CiUrlWork,
    Iptc4xmpExt:AOSourceInvURL, plus:LicensorURL, and any item of xmp:Identifier;
  • a value carrying a qualifier, most often an xml:lang on a plain text field;
  • a language alternative holding a language beside x-default;
  • an rdf:Seq where the model writes an rdf:Bag, or the reverse.

The question this issue holds open: should the model grow to express them, so the typed accessor
reports the value and the writer puts it back as it found it?

Sketch of the fork:

  • Leave it. The graph is intact and the field is reachable through other. Cheapest, and the
    typed view stays plain data (Option<String>, Vec<String>) as AGENTS.md's C-portability
    convention wants. A caller reading licensors()[0].web_url on a PLUS-conformant file written
    with rdf:resource gets None and has to know to look in other.
  • Carry the value kind. Replace the URL fields' String with a type that remembers whether it
    was rdf:resource. Breaking for three public fields, and Entity::identifiers is a Vec<String>
    where the kind is per item, so it needs a per-item type — a heavier public API for what is
    otherwise plain data.
  • Carry the whole language alternative. Option<String> becomes a list of (tag, text), which
    is the honest model of an rdf:Alt but changes the ergonomics of every descriptive field.
  • Carry qualifiers. Decision 4 of round 4 rejected this as larger than gamut-iptc: IPTC Extension structures + IIM records 3-9 #422's scope; it would
    still leave the general case open, because a qualifier can hang off anything.

Whichever way it goes, it should be decided once for the whole extension module rather than per
field, and the answer interacts with #591 (whether other should be public at all) and #573
(whether emission should be fallible).

Scope: crates/gamut-iptc/src/extension.rs. Refs #422, and PR #540, where the retention rule and
its enumeration landed.

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