You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
gamut-png surfaces a file's XMP packet as its own field — DecodedPng::xmp / PngMetadata::xmp,
raw bytes — rather than as an entry in texts. The packet is nonetheless an ordinary iTXt chunk
(§11.3.3.4) under the keyword §11.3.3.1 Table 21 reserves for it, so everything a TextChunk
already carries applies to it: a compression flag, a language tag, a translated keyword, and a
position in the file's chunk order.
Because the field carries only bytes, PR #550 had to add a second public type, XmpFraming, and a
second field, xmp_framing, to hold the rest of the chunk. That closed the immediate defect (a
compressed packet was being rewritten uncompressed — a 354-byte iTXt became 3 734 bytes) but
left three seams that consolidating the packet into texts would close together:
Two fields that must agree.xmp and xmp_framing are Some together when the decoder
produces them, but nothing in the type system says so, and a caller assembling a PngMetadata
by hand can set one without the other.
The packet is a single-value payload implemented inside a list.Ancillary::add_xmp has to retain away a previous packet so that setting it twice writes one chunk, which every other
single-value payload (iccp, exif) gets for free from being an Option field.
File order is lost. A carry emits the packet first among the annotations regardless of
where its chunk sat in the source, because it is set before the texts loop.
Why it is a separate decision
It reshapes a public type on a crate that is about to take its first version bump: xmp would
either disappear or become a convenience accessor over texts, and XmpFraming would be retired.
Whether the packet should keep a dedicated read surface at all — callers hand it straight to gamut_metadata::MetadataBlock::Xmp, which is why the field exists — is the question to settle
first, and it is not one PR #550's record covers.
Options to weigh
Keep texts as the single list, and make xmp a #[must_use] accessor that finds the reserved
keyword. Costs a scan; keeps the ergonomic read path.
Keep both surfaces but make the pairing unrepresentable: replace xmp: Option<Vec<u8>> + xmp_framing: Option<XmpFraming> with one Option<XmpPacket>.
references/png/png-3.html §11.3.3.1 Table 21 (the reserved keyword and its recommended framing),
§11.3.3.4 (iTXt), §14.3.2 (a reader may not assume ancillary chunk ordering — which bounds how
much (3) actually costs).
What
gamut-pngsurfaces a file's XMP packet as its own field —DecodedPng::xmp/PngMetadata::xmp,raw bytes — rather than as an entry in
texts. The packet is nonetheless an ordinaryiTXtchunk(§11.3.3.4) under the keyword §11.3.3.1 Table 21 reserves for it, so everything a
TextChunkalready carries applies to it: a compression flag, a language tag, a translated keyword, and a
position in the file's chunk order.
Because the field carries only bytes, PR #550 had to add a second public type,
XmpFraming, and asecond field,
xmp_framing, to hold the rest of the chunk. That closed the immediate defect (acompressed packet was being rewritten uncompressed — a 354-byte
iTXtbecame 3 734 bytes) butleft three seams that consolidating the packet into
textswould close together:xmpandxmp_framingareSometogether when the decoderproduces them, but nothing in the type system says so, and a caller assembling a
PngMetadataby hand can set one without the other.
Ancillary::add_xmphas toretainaway a previous packet so that setting it twice writes one chunk, which every othersingle-value payload (
iccp,exif) gets for free from being anOptionfield.where its chunk sat in the source, because it is set before the
textsloop.Why it is a separate decision
It reshapes a public type on a crate that is about to take its first version bump:
xmpwouldeither disappear or become a convenience accessor over
texts, andXmpFramingwould be retired.Whether the packet should keep a dedicated read surface at all — callers hand it straight to
gamut_metadata::MetadataBlock::Xmp, which is why the field exists — is the question to settlefirst, and it is not one PR #550's record covers.
Options to weigh
textsas the single list, and makexmpa#[must_use]accessor that finds the reservedkeyword. Costs a scan; keeps the ergonomic read path.
xmp: Option<Vec<u8>>+xmp_framing: Option<XmpFraming>with oneOption<XmpPacket>.Spec
references/png/png-3.html§11.3.3.1 Table 21 (the reserved keyword and its recommended framing),§11.3.3.4 (
iTXt), §14.3.2 (a reader may not assume ancillary chunk ordering — which bounds howmuch (3) actually costs).
Where
crates/gamut-png/src/decoded.rs,crates/gamut-png/src/ancillary.rs,crates/gamut-png/src/encoder.rs,crates/gamut-png/tests/preservation.rs,crates/gamut-png/STATUS.md.Refs #483. Raised by the review of #550.