Skip to content

gamut-xmp: consider canonicalizing a well-known namespace URI on read (Darwin Core trailing slash) #547

Description

@justin13888

gamut-xmp registers Darwin Core as http://rs.tdwg.org/dwc/index.htm, and WellKnownNs::from_uri
additionally recognises http://rs.tdwg.org/dwc/index.htm/ (DWC_URI_TRAILING_SLASH) as a
read alias, because exiv2 appends / to any namespace URI ending in neither / nor # before
registering it with XMPCore (third_party/exiv2/src/properties.cpp, XmpProperties::registerNs),
and Darwin Core is the only registered schema whose URI ends in neither.

The alias resolves a prefix, not a URI. Reading does not canonicalize: the parsed graph keeps
the slashed URI its packet declared, and XmpMeta::to_packet writes that URI straight back. So for
a packet an exiv2/XMPCore writer produced:

  • the graph re-serializes under the dwc prefix rather than a synthesized ns1 — the intended win;
  • meta.get_text(WellKnownNs::DarwinCore.uri(), "Record") returns None, while
    meta.get_text(DWC_URI_TRAILING_SLASH, "Record") returns the value.

That is the naive use of the registry, and it is the asymmetry this option would close.

The option

Canonicalize the URI on read: when the reader resolves a declared namespace URI through
WellKnownNs::from_uri, store ns.uri() in the graph instead of the declared string, so a caller
can always resolve a well-known property by WellKnownNs::…​.uri() regardless of which spelling the
writer used.

Why it is not done today

Identity preservation is this crate's consistent posture: rewriting a caller's URI to the registered
form would change bytes exiv2 wrote, so a packet read and written back would no longer be
byte-identical to its input for the one schema affected. Prefix fidelity was the stated intent of
the alias, and no consumer needs URI canonicalization yet.

What it would leave asymmetric either way

  • As today: from_uri(u).map(WellKnownNs::uri) == Some(u) holds for every registry entry and
    not for the alias — pinned by
    crates/gamut-xmp/src/namespace.rs::the_trailing_slash_alias_is_the_only_uri_from_uri_does_not_hand_back.
    Callers must resolve by the URI the packet carries.
  • If canonicalized: the graph would no longer be a faithful record of the bytes read, and
    round-tripping an exiv2-written dwc packet would change its namespace URI. Any such change needs
    to say which of the two properties it is giving up, and would want a knob (a ConvertPolicy-style
    opt-in) rather than a silent rewrite.

Acceptance, if taken

  • A decision recorded in crates/gamut-xmp/STATUS.md naming which property is given up.
  • Either behaviour pinned by a test that reads an XMPCore-written dwc packet and asserts the URI
    the graph carries.
  • README.md, STATUS.md and WellKnownNs::from_uri's own documentation updated together — that
    documentation is where a caller meets the trap.

Raised while reviewing #507 (issue #421). No code change is proposed here; this records the option
and the asymmetry so a consumer that needs it has somewhere to say so.

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