Skip to content

research: normalize the .lnk format — two incompatible variants exist today #1357

Description

@zackees

Summary

There are two mutually incompatible .lnk formats in the FastLED ecosystem today. The one file actually committed to FastLED cannot be read by the tool named lnk. This issue is to research and decide a single normalized format plus a migration path.

The split

Format A — plain text (FastLED#2284). Committed today at FastLED/FastLED:examples/AudioUrl/data/track.mp3.lnk on origin/master:

# .lnk asset link file — see FastLED issue #2284.
# The first non-comment line is the URL this asset resolves to.
# Lines starting with '#' and blank lines are ignored.
# Additional lines (metadata like sha256=, fallback=) are reserved for
# future use and are ignored by the v1 parser.
https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3

Format B — JSON v1 (fbuild crates/fbuild-toolchain/src/lnk/format.rs). What fbuild lnk add emits and fbuild lnk pull consumes:

{
  "sha256": "164804d94802dd96cd8cd37f7528ca6d30f8fd9396e812fe67ec6164bbdd2282",
  "size": 6051840,
  "url": "https://raw.githubusercontent.com/FastLED/assets/main/examples/FxLedmapper32x32/video1.rgb",
  "v": 1
}

format.rs::from_raw parses JSON only and hard-rejects anything else, so Format A fails outright under fbuild lnk pull / check.

Why this matters now

  • examples/AudioUrl is on origin/master in Format A. Any fbuild lnk pull over that tree errors on it.
  • New work (examples/Fx/FxLedmapper32x32) uses Format B.
  • A third variant was independently drafted during design work — key=value with repeated url= for fallbacks — which converged on Format A's reserved sha256= / fallback= keys rather than Format B. That three-way convergence is evidence the format was never actually settled.
  • FastLED/fbuild#1356 (storage targets and diagnostics) depends on knowing which format it is annotating. This should probably be decided before that design lands.

Research needed

Prior art is genuinely split, which is why this needs research rather than a coin flip:

  • git-LFS uses a text key-value pointer — and it is the closest analogue to this use case:
    version https://git.lfs.github.com/spec/v1
    oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
    size 12345
    
    Deliberately line-oriented so it diffs cleanly and merges predictably in git.
  • DVC uses YAML (.dvc files).
  • Bazel uses Starlark declarations, not sidecar files.
  • Nix uses expressions, not sidecars.

The git-LFS precedent is a real argument for text, and it is the system whose problem most resembles ours (pointer files checked into git, standing in for large binaries).

Questions to answer:

  1. Text or JSON? JSON is trivially machine-parseable and already implemented in fbuild. Text diffs and merges better in git — the property git-LFS optimized for and the reason it rejected structured formats. Which matters more here, given these files live in git and are edited rarely but reviewed often?
  2. Should the parser accept both? A tolerant reader (sniff { → JSON, else text) is cheap and eliminates the migration cliff. Does permanent dual support cost more in confusion than it saves in transition?
  3. Migration path for examples/AudioUrl. Convert to the winner, or leave and make the parser tolerant? Note it also lacks a sha256 entirely, so converting it requires fetching and hashing the upstream MP3 — which is a third-party URL that could change.
  4. What is the versioning story? Format B has v: 1 and format.rs:110-116 hard-rejects v != 1, so a v2 bump breaks every older fbuild on sight. Adding fields to v1 is safe (unknown keys are ignored by both LnkFileRaw and FastLED's ci/asset_resolver.py). Any normalization must not require a version bump, or must accept breaking older clients.
  5. Is sha256 required or optional? Format A has none. Format B treats it as present-in-practice. A .lnk without a digest gets fetch but no integrity — should that be an error, a warning, or allowed?
  6. Multiple URLs / fallbacks? Format A reserves fallback=. Format B has a single url. FastLED's ci/asset_resolver.py accepts a list for url. CDN-primary-with-raw-fallback is a real need (see feat: structured manifest.json index + CDN serving for FastLED assets assets#1), so the normalized format should have an answer.

Acceptance criteria

  • A single normalized format is specified and documented
  • examples/AudioUrl/data/track.mp3.lnk parses successfully under fbuild lnk check
  • examples/Fx/FxLedmapper32x32/data/video1.rgb.lnk continues to parse
  • A stated position on dual-format support (permanent, transitional with an end date, or never)
  • FastLED's ci/asset_resolver.py and its tests updated to match
  • Migration documented for anyone with existing .lnk files

Related

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

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions