gamut_iptc::extension's to_xmp methods are infallible: they return an XmpValue, matching
gamut_exif::GpsInfo::to_ifd's shape. That leaves them with no way to report a value they cannot
express, so the only choices at such a value are to write something the declared type does not
admit, or to drop it.
PR #540 took the second: put_number now skips a non-finite coordinate (NaN, ±inf) instead of
writing the text NaN/inf/-inf, which is not an XMP Real and which nothing reads back as a
number. That is the right default — a graph that says nothing is better than a graph that lies —
but it is still a silent drop through safe public API, and the caller who set the field is not told.
The question this issue holds open: should structure emission become fallible instead?
Sketch of the fork:
- Keep it infallible, skip and document (what ships today). Cheapest, keeps the
GpsInfo shape
the crate deliberately mirrors, and keeps a to_xmp() usable in an expression. A caller who
hands in f64::NAN gets no signal.
- Return
Result<XmpValue, IptcError>. Honest, and consistent with the crate's strict-write
posture elsewhere (IptcWriter rejects an overlong or unencodable value rather than truncating).
It is a breaking change to a published v1 crate — to_xmp is public on seven types — and it
makes the setters on PhotoMetadata fallible too, or forces them to swallow the error.
- Make the coordinate fields un-representable-if-invalid (a
Finite(f64) newtype, or private
fields with a checked constructor). No error type, no breaking signature, but a heavier public
API for what is otherwise plain data, and it diverges from the "configs are plain data" convention
in AGENTS.md.
Whichever way it goes, it should be decided once for the whole extension module rather than per
field, and the same answer should cover the other value a projection cannot express (a numeric field
whose text does not parse, which reads as absent today).
Scope: crates/gamut-iptc/src/extension.rs. Refs #422, and PR #540 where the current behaviour and
its test (a_non_finite_coordinate_is_not_written) landed.
gamut_iptc::extension'sto_xmpmethods are infallible: they return anXmpValue, matchinggamut_exif::GpsInfo::to_ifd's shape. That leaves them with no way to report a value they cannotexpress, so the only choices at such a value are to write something the declared type does not
admit, or to drop it.
PR #540 took the second:
put_numbernow skips a non-finite coordinate (NaN,±inf) instead ofwriting the text
NaN/inf/-inf, which is not an XMPRealand which nothing reads back as anumber. That is the right default — a graph that says nothing is better than a graph that lies —
but it is still a silent drop through safe public API, and the caller who set the field is not told.
The question this issue holds open: should structure emission become fallible instead?
Sketch of the fork:
GpsInfoshapethe crate deliberately mirrors, and keeps a
to_xmp()usable in an expression. A caller whohands in
f64::NANgets no signal.Result<XmpValue, IptcError>. Honest, and consistent with the crate's strict-writeposture elsewhere (
IptcWriterrejects an overlong or unencodable value rather than truncating).It is a breaking change to a published v1 crate —
to_xmpis public on seven types — and itmakes the setters on
PhotoMetadatafallible too, or forces them to swallow the error.Finite(f64)newtype, or privatefields with a checked constructor). No error type, no breaking signature, but a heavier public
API for what is otherwise plain data, and it diverges from the "configs are plain data" convention
in
AGENTS.md.Whichever way it goes, it should be decided once for the whole
extensionmodule rather than perfield, and the same answer should cover the other value a projection cannot express (a numeric field
whose text does not parse, which reads as absent today).
Scope:
crates/gamut-iptc/src/extension.rs. Refs #422, and PR #540 where the current behaviour andits test (
a_non_finite_coordinate_is_not_written) landed.