Context
zencodec::exif is read + filter today (PR #17): Exif::parse → filtered → to_bytes, plus Metadata::filtered. There is no public write API — we never construct EXIF fields from user input; a rewrite only preserves/prunes the source's bytes.
A future need may arise: a pipeline that injects Orientation or stamps a Copyright string on every processed image. This issue records the agreed design so it can be built when a concrete consumer lands. Deferred for now (no API added without a real use).
Agreed shape
exif::Builder (construct from scratch) + Exif::edit() (edit a parsed blob), each ending in build() -> Vec<u8>, reusing the existing canonical serializer (to_bytes).
- Mechanism: relax
Entry.value: &'a [u8] → Cow<'a, [u8]> so parsed entries stay borrowed (zero-copy reads unchanged) while injected ones are owned. (Alternative: a separate Builder that copies entries — editing allocates anyway.) Re-fuzz after.
- Encoding (spec-correct): a string setter picks the TIFF type — ASCII (type 2) when pure 7-bit, else UTF-8 (type 129) — NUL-terminated, count incl. NUL. Never stuff non-ASCII into a type-2 field.
- Interop default: ASCII-if-possible, else UTF-8 (129). Type 129 has thin reader support today (ExifTool reads it; kamadak-exif / Pillow / most don't), so prefer ASCII when the string allows. For broad readability of a copyright, a likely companion is also writing XMP
dc:rights (universally UTF-8).
- Reconcile
Metadata::orientation (the field codecs apply) with any Orientation entry the builder writes into the EXIF blob — keep them consistent.
Additive (semver-minor) when implemented. Design recorded in docs/spec.md → "Planned (not implemented): EXIF write / edit path".
Context
zencodec::exifis read + filter today (PR #17):Exif::parse→filtered→to_bytes, plusMetadata::filtered. There is no public write API — we never construct EXIF fields from user input; a rewrite only preserves/prunes the source's bytes.A future need may arise: a pipeline that injects Orientation or stamps a Copyright string on every processed image. This issue records the agreed design so it can be built when a concrete consumer lands. Deferred for now (no API added without a real use).
Agreed shape
exif::Builder(construct from scratch) +Exif::edit()(edit a parsed blob), each ending inbuild() -> Vec<u8>, reusing the existing canonical serializer (to_bytes).Entry.value: &'a [u8]→Cow<'a, [u8]>so parsed entries stay borrowed (zero-copy reads unchanged) while injected ones are owned. (Alternative: a separateBuilderthat copies entries — editing allocates anyway.) Re-fuzz after.dc:rights(universally UTF-8).Metadata::orientation(the field codecs apply) with any Orientation entry the builder writes into the EXIF blob — keep them consistent.Additive (semver-minor) when implemented. Design recorded in
docs/spec.md→ "Planned (not implemented): EXIF write / edit path".