Skip to content

feat(lnk): accept the text-format .lnk alongside JSON - #1362

Merged
zackees merged 1 commit into
mainfrom
feat/lnk-accept-text-format
Aug 23, 2026
Merged

feat(lnk): accept the text-format .lnk alongside JSON#1362
zackees merged 1 commit into
mainfrom
feat/lnk-accept-text-format

Conversation

@zackees

@zackees zackees commented Aug 23, 2026

Copy link
Copy Markdown
Member

Problem

Two incompatible .lnk formats exist in the FastLED ecosystem, and fbuild parsed only one of them. A text-format file failed with:

invalid .lnk JSON: expected value at line 1 column 1

The text format is not legacy cruft — it has three implementations and is live in the shipping product:

Layer Location
C++ runtime src/fl/stl/url.h:274 fl::parse_lnk(), :325 parse_lnk_with_metadata()
C++ asset API src/fl/asset/asset.hFL_ASSET("data/track.mp3")
Python build ci/compiler/asset_scanner.py — emits the WASM manifest

And examples/AudioUrl/data/track.mp3.lnk is committed on FastLED master in that format — meaning the one .lnk actually in the repo could not be read by the tool named lnk.

Change

from_str_any() sniffs the first non-blank, non-comment character: { routes to the existing JSON parser, anything else to a new text parser matching the C++ grammar — first non-comment line is the URL, subsequent key=value lines are metadata, unknown keys ignored for forward-compat.

from_path() now uses it, so every existing caller (lnk pull, lnk check, the embed stage) gains both formats with no call-site changes. JSON remains canonicalfbuild lnk add is unchanged.

sha256 stays mandatory

The text format treats the digest as optional; fbuild does not, and this PR keeps it that way. The resolver caches by content digest, so a .lnk without one cannot be content-addressed or verified — relaxing that to accommodate the text format would give up the guarantee the whole cache is built on.

Instead the error is made actionable:

text-format .lnk for <url> has no `sha256=` line; fbuild caches by content
digest and cannot verify or content-address without one. Add a
`sha256=<64 hex chars>` line, or regenerate the file with `fbuild lnk add <url>`.

Note this means examples/AudioUrl/data/track.mp3.lnk still needs a digest added — but it now gets a message saying so, instead of a JSON parse error pointing at column 1.

Verification

End to end with a real asset, using a text-format .lnk:

$ fbuild lnk pull <dir>
ok   .../data/screenmap.json.lnk  →  ~/.fbuild/prod/cache/archives/lnk-blobs/.../a6851e2a…/screenmap.json
lnk pull: 1 ok, 0 failed (of 1)

And the integrity path, using a deliberately wrong digest — the fetch is rejected and the .partial is never promoted:

FAIL .../track.mp3.lnk: package error: sha256 mismatch ...
  expected 0000…0000, got cadd2666c5571e12fafdb21697b26aef6f196a5a9c28e708129870167679991d
lnk pull: 1 ok, 1 failed (of 2)
  • 43 lnk tests pass, 7 new: text parsing with sha256, unknown-key tolerance, missing-sha256 message content, missing-URL rejection, leading-whitespace JSON routing, #-before-JSON rejected as malformed JSON (documenting that boundary), and JSON/text forms producing an identical LnkFile.
  • cargo clippy -p fbuild-toolchain --lib clean.

Refs #1357, FastLED/FastLED#3986

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for reading both canonical JSON and FastLED-compatible text .lnk files.
    • Text files now support comments and additional metadata while extracting required URL and SHA-256 information.
    • Format detection now tolerates leading whitespace and comments.
  • Bug Fixes

    • Invalid files with missing URLs or digests are now rejected with validation errors.

Two incompatible `.lnk` formats exist in the FastLED ecosystem. fbuild
parsed only JSON, so text-format files were rejected with a confusing
"invalid .lnk JSON: expected value at line 1 column 1".

The text format is not legacy cruft — it has three implementations and is
live in the shipping product:

  - fl::parse_lnk_with_metadata()  src/fl/stl/url.h      (C++ runtime)
  - fl::asset / FL_ASSET           src/fl/asset/asset.h  (C++ API)
  - _parse_lnk_content()           ci/compiler/asset_scanner.py

`examples/AudioUrl/data/track.mp3.lnk` is committed on FastLED master in
that format and is unreadable by the tool named `lnk`.

`from_str_any()` now sniffs the first non-blank, non-comment character:
`{` routes to the JSON parser, anything else to a new text parser
matching the C++ grammar (first non-comment line is the URL, subsequent
key=value lines are metadata, unknown keys ignored for forward-compat).
`from_path()` uses it, so every existing caller gains both formats.

`sha256` stays mandatory for the text form too. The resolver caches by
content digest, so a `.lnk` without one cannot be content-addressed or
verified — weakening that to accommodate the text format would give up
the guarantee the cache is built on. The error names the file and says
how to fix it rather than failing generically.

JSON remains canonical: `fbuild lnk add` is unchanged.

Verified end to end with a real asset — text-format .lnk fetched and
sha256-verified into the blob cache, and a deliberately wrong digest
rejected without promoting the .partial. 43 lnk tests pass, 7 new.

Refs #1357, FastLED/FastLED#3986

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e2fdbc1c-be9f-4a33-8c0c-55f9366dc9ec

📥 Commits

Reviewing files that changed from the base of the PR and between 49ec69c and 2ce1340.

📒 Files selected for processing (1)
  • crates/fbuild-toolchain/src/lnk/format.rs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

LnkFile now accepts canonical JSON and FastLED-compatible text .lnk manifests. Detection ignores leading whitespace, blank lines, and comments. Text parsing extracts the URL and SHA-256 digest, ignores unknown metadata, and validates required fields.

Changes

LNK parsing

Layer / File(s) Summary
Format detection and manifest parsing
crates/fbuild-toolchain/src/lnk/format.rs
Added format detection and text parsing for URLs, sha256= metadata, comments, blank lines, and unknown keys.
File integration and parsing validation
crates/fbuild-toolchain/src/lnk/format.rs
Updated from_path to use format-agnostic parsing. Added tests for format equivalence, detection, and validation errors.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 2ce13

The PR adds support for text-format .lnk files while preserving JSON handling and mandatory sha256 verification. No actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely states that text-format .lnk files are added alongside JSON support.
Docstring Coverage ✅ Passed Docstring check was indeterminate for this PR — some files could not be analyzed in time. Not blocking.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/lnk-accept-text-format

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@zackees
zackees merged commit 21e7295 into main Aug 23, 2026
2 of 98 checks passed
@zackees
zackees deleted the feat/lnk-accept-text-format branch August 23, 2026 01:11
zackees added a commit to FastLED/FastLED that referenced this pull request Aug 23, 2026
`examples/AudioUrl/data/track.mp3.lnk` carried no sha256, so fbuild could
not verify or content-address it -- fbuild requires a digest on every
`.lnk` (FastLED/fbuild#1357).

Adding one to the existing URL would have pinned a digest to
soundhelix.com, where any upstream re-encode breaks the build. The track
is now mirrored into FastLED/assets and the `.lnk` points there, so the
digest stays valid:

    sha256=cadd2666c5571e12fafdb21697b26aef6f196a5a9c28e708129870167679991d
    size  =8,945,229 bytes

Verified byte-identical against the origin before and after upload.

The file stays in the TEXT format deliberately. I first converted it to
fbuild's JSON schema and `fl_asset_asset` caught the mistake: the C++
runtime's `fl::parse_lnk` reads only the text form, so it took `{` as the
URL and resolution returned host `{`. That is precisely the format split
documented in FastLED/fbuild#1357, and the reason fbuild learned to read
text `.lnk` files in FastLED/fbuild#1362 rather than the reverse.

The test's host assertion moves with the URL, and gains a comment saying
why the format cannot change here -- the next person to "tidy" this into
JSON should hit the explanation before the failure.

Note the released fbuild (2.5.20) predates #1362, so `fbuild lnk pull`
will not read this file until the next release. The C++ runtime and the
Python scanner both accept it today.

bash lint clean, bash test --cpp passes, AudioUrl builds for WASM.

Refs FastLED/fbuild#1357

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
zackees added a commit to FastLED/FastLED that referenced this pull request Aug 23, 2026
`asset.h` said fbuild scans `<sketch>/data/` for `.lnk` files and emits a
manifest. It does not -- `ci/compiler/asset_scanner.py` does, driven from
`ci/wasm_build.py`, writing `fastled_js/asset_manifest.json`.

The distinction matters because the two read different formats. fbuild's
`.lnk` parser was JSON-only until FastLED/fbuild#1362; the scanner reads
the text form this runtime parses, and now the JSON form too. Someone
debugging a missing asset who believes fbuild produced the manifest looks
in the wrong tool.

Last item on FastLED/fbuild#1357 that is a plain factual fix; the
remaining one there is the long-term format direction, which is a
maintainer call.

Refs FastLED/fbuild#1357

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant