Summary
.lnk currently serves two roles with different consumers, guarantees, and formats. Both parsers now accept both spellings (#1362, FastLED/FastLED#3990), so nothing is broken — but the ambiguity remains, and it is the kind that produces confident wrong edits.
Spun out of #1357, whose concrete work is complete.
The two roles
|
Runtime asset link |
Build-time blob pointer |
| Parsed by |
fl::parse_lnk (C++, on-device) |
fbuild (Rust, build host) |
| Format |
text: URL line + key=value |
JSON: {v, url, sha256, size, extract} |
sha256 |
optional, unenforced |
required |
| Written by |
hand |
fbuild lnk add |
| Extras |
fallback= |
extract (file/zip/tar.gz) |
They are not competing drafts of one thing. The runtime form has to be parseable on an MCU, where fl::parse_lnk is deliberately allocation-light and there is no JSON parser worth carrying. The build-time form needs a mandatory digest because the resolver caches by content.
Why the shared extension is a hazard
It reads as one concept, so people normalize toward whichever form they met first. That already happened once, in FastLED/FastLED#4012: converting examples/AudioUrl/data/track.mp3.lnk to fbuild's JSON schema looked like tidying, and produced
tests/fl/asset/asset.cpp:108: { == www.soundhelix.com
because fl::parse_lnk took { as the URL. A test caught it. A sketch author gets a silently wrong URL instead.
Recommendation
Give the roles distinct extensions — keep .lnk for the runtime asset link, and use something else for build-time blob pointers — rather than converging the formats.
The alternative, converging on JSON, means putting a JSON parser in the MCU runtime for no user-visible benefit. Converging on text means giving up the mandatory digest that fbuild's content-addressed cache depends on. Distinct extensions cost one rename and make the mistake above impossible to express.
Open questions
- What to call the build-time one.
.blob, .fetch, .remote — something that does not read as a generic "link".
- Migration:
fbuild lnk add writes the new extension; existing files keep working since both parsers are tolerant. Deprecation window?
- Does
assets.json (multi-asset manifest, parsed by asset_scanner.py) fold into whichever the build-time form becomes?
Related
Summary
.lnkcurrently serves two roles with different consumers, guarantees, and formats. Both parsers now accept both spellings (#1362, FastLED/FastLED#3990), so nothing is broken — but the ambiguity remains, and it is the kind that produces confident wrong edits.Spun out of #1357, whose concrete work is complete.
The two roles
fl::parse_lnk(C++, on-device)key=value{v, url, sha256, size, extract}sha256fbuild lnk addfallback=extract(file/zip/tar.gz)They are not competing drafts of one thing. The runtime form has to be parseable on an MCU, where
fl::parse_lnkis deliberately allocation-light and there is no JSON parser worth carrying. The build-time form needs a mandatory digest because the resolver caches by content.Why the shared extension is a hazard
It reads as one concept, so people normalize toward whichever form they met first. That already happened once, in FastLED/FastLED#4012: converting
examples/AudioUrl/data/track.mp3.lnkto fbuild's JSON schema looked like tidying, and producedbecause
fl::parse_lnktook{as the URL. A test caught it. A sketch author gets a silently wrong URL instead.Recommendation
Give the roles distinct extensions — keep
.lnkfor the runtime asset link, and use something else for build-time blob pointers — rather than converging the formats.The alternative, converging on JSON, means putting a JSON parser in the MCU runtime for no user-visible benefit. Converging on text means giving up the mandatory digest that fbuild's content-addressed cache depends on. Distinct extensions cost one rename and make the mistake above impossible to express.
Open questions
.blob,.fetch,.remote— something that does not read as a generic "link".fbuild lnk addwrites the new extension; existing files keep working since both parsers are tolerant. Deprecation window?assets.json(multi-asset manifest, parsed byasset_scanner.py) fold into whichever the build-time form becomes?Related