Files
aiongg f3bb7a9f30 CI: one test binary per crate, line tables only, one WASM check (#2710)
* CI: dev profile keeps line tables for workspace crates and no debug info for dependencies

* Control server tests: persistent_requests_and_slow_replies_outlive_the_idle_read_timeout no longer races the idle timeout

Each request (and the closing half-shutdown) reaches the socket before the
worker reads, so on a slow machine only the reply waits outlast the 100 ms
idle timeout, as the test intends. The idle test sends its input the same
way, and the no-frames test allows 5 s instead of 2 s to give up.

* CI: one integration-test binary per crate

Each crate's tests/*.rs become modules of tests/it/main.rs (51 test files
into 13 binaries, plus 6 that stay their own). Inner #![cfg] attributes
move to the mod lines. Files that change state for the whole process keep
a binary of their own: codecs jxl_tail_heap and raw sr2_heap (dhat global
allocator), gpu shutdown, shutdown_first and memory, ui-egui shutdown.
Docs, comments and the GPU probe name the new paths and targets
(--test it <module>::); the CI report names an it binary's skips after
the crate.

* CI: tests under nextest, doctests apart, one wasm check

xtask ci runs the tests with cargo nextest run --lib --bins --tests when
cargo-nextest is installed, else cargo test with the same targets and a
one-line notice; doctests run after them with cargo test --workspace --doc.
The heif and hardware GPU steps use the same runner. Examples stay out of
the test build (clippy --all-targets still checks them). Concurrent tests
under nextest follow the RUST_TEST_THREADS cap (NEXTEST_TEST_THREADS).
The wasm check is one cargo check --keep-going over the same crates, and
clippy runs with --keep-going.

* CI: tests run under cargo test by default, nextest with LIGHTCRAFT_NEXTEST=1 (per-process scene cache)
2026-10-23 13:34:30 -04:00
..
2026-09-30 11:00:48 -04:00

lightcraft-tiff (L0)

TIFF / IFD reader and writer. Used by lightcraft-raw (DNG, CR2, NEF, ARW…), lightcraft-meta (Exif) and later the TIFF/DNG exporters.

Features

  • Classic TIFF and BigTIFF, little- and big-endian (II/MM). Also accepts the TIFF-like magic numbers of some raw formats (ORF IIRO/IIRS, RW2 IIU) when ParseOptions::accept_raw_magic is set (default).
  • Every field type: BYTE, ASCII, SHORT, LONG, RATIONAL, SBYTE, UNDEFINED, SSHORT, SLONG, SRATIONAL, FLOAT, DOUBLE, IFD, LONG8, SLONG8, IFD8.
  • IFD chain + SubIFDs (330) + Exif (34665) / GPS (34853) / Interoperability (40965) pointer IFDs, resolved into a tree (Ifd::sub_ifds, exif, gps, interop). Entry::offset records the absolute position of each value (needed for maker notes and embedded blobs).
  • parse_ifd_at(data, offset, order, base, bigtiff, opts) parses an IFD whose offsets are relative to an arbitrary base; makernote::parse_makernote knows the header / byte-order / offset-base conventions of Canon, Nikon (types 1 and 3), Sony, Fujifilm, Olympus (old and new), Panasonic and Pentax notes.
  • image::ImageInfo — width/height, bits, samples, compression, photometric, planar config, predictor, sample format and the strip or tile chunk list (chunks(), chunk_bytes()); missing byte counts are inferred.
  • directory_entries, entry_span, ParseOptions::budget_for and decode_value are the reader's own rules (directory layout and entry limit, which entries it reads, its value budget, value decoding), for callers that must select entries exactly as parse_ifd_at would without decoding the whole directory (lightcraft-raw's Sony SR2Private lookup).
  • TiffWriter writes IFD chains with strips or tiles, SubIFDs and pointer IFDs, in either byte order, classic or BigTIFF; writer::rational / srational approximate floats as rationals.

Robustness

The reader never panics on malformed input (proptests feed random and mutated files): offsets are bounds-checked; out-of-range or unknown-type entries are skipped; IFD loops are detected; IFD count, nesting depth and entries per IFD are limited; at most 65,536 directory entry slots (ParseOptions::max_entries_total) are accepted across the main IFD chain and all child IFDs, even when tables overlap at distinct offsets, and an IFD past that bound ends the chain or is skipped like any other bad IFD after the first; a next-IFD pointer is followed only when every declared entry was read, with the counts compared as 64-bit numbers (a BigTIFF declaring 4,294,967,297 entries but holding one can't pass for a whole directory on a 32-bit target); the total bytes of decoded values are capped at 8 × input + 1 MiB so a file cannot make us allocate far more than its own size.

Sources

Public specifications only: TIFF 6.0 (Adobe, 1992), the TIFF 6.0 supplements (IFD type, SubIFDs), the BigTIFF format description (AWare Systems), Adobe DNG Specification 1.7 (tag numbers), CIPA DC-008 Exif 2.32, and the ExifTool tag-name documentation (maker-note header conventions, prose only). No third-party code was consulted.