compression: xxHash32/xxHash64 in std/digest and the LZ4 frame format (step 2 of #121) #781
Labels
No labels
loop
queue/failed
queue/queued
ready
status/parked
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
torbscript/language#781
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Step 2 of #121 (FIRST-PARTY.md gap 26). Step 1 (#432) landed the Snappy and LZ4 block formats in
std/compression. The LZ4 frame format needs two checksums, xxHash32 (header checksum byte, block and content checksums) and, for the content checksum, xxHash32 as well; xxHash64 is the sibling that Zstandard's frame content checksum uses (step 3), so both land instd/digestnow.Design
Ordinary TorbScript, no native, no syntax change, no new driver flag, no std name the compiler looks up by string. Touches the seed: no. Implemented from the public specifications (xxHash
doc/xxhash_spec.md, LZ4lz4_Frame_format.md); the BSD reference code is only used to produce test vectors.std/digest/src/xxhash.trb(new, exported fromstd/digest/src/lib.trb):Bytes.xxHash32(seed: Int = 0): Int(unsigned 32-bit in anInt) andBytes.xxHash64(seed: Int = 0), named like the existing digest methods ofBytes(look atsha1.trb/md5.trbfor the precedent and the import form). Match the 64-bit wrap-around arithmetic of the language'sIntas the existing digests do; if the 64-bit variant needs unsigned multiplication the language lacks, state it in the PR and ship xxHash32 plus the LZ4 frame only, keeping xxHash64 as step 2b.std/compression/src/lz4_frame.trb(new):Bytes.lz4Framed(): Byteswrites one LZ4 frame (magic0x184D2204, FLG with version 01, block independence on, block checksums off, content checksum on, no content size, BD with 4 MiB max block size, header checksum byte(xxHash32(descriptor) >> 8) & 0xFF, data blocks of at most 4 MiB each compressed withlz4BlockCompressedor stored uncompressed when that is not smaller, EndMark, content checksum); deterministic.Bytes.lz4Unframed(maximumSize: Int): Result<Bytes, CompressionError>reads every valid frame: all FLG/BD options (block independence on or off with linked blocks, block checksum, content size, content checksum, dictionary id fails with a clear reason), uncompressed blocks, and skippable frames (0x184D2A5x) between frames; concatenated frames are decoded one after the other. Fails on bad magic, bad header checksum, block over the declared maximum, checksum mismatch, truncated input, and output overmaximumSize; never allocates by a declared size.CompressionError.Acceptance criteria
xxHash32(andxxHash64, see above) produce the published vectors: empty input with seed 0 (0x02CC5D05for xxHash32,0xEF46DB3751D8E999for xxHash64), the spec's other documented vectors, and at least two longer inputs (over 16 and over 32 bytes, so the striped main loop runs) with values taken from a reference implementation and committed as hex in the test.lz4Framed/lz4Unframedround-trip: empty input, one byte, 70 000 bytes of text, 100 000 pseudo-random bytes (stored blocks), and an input larger than one block.lz4command line tool (committed as hex, at least one with block checksums and linked blocks, one with content size) decodes to the original bytes; a skippable frame before a frame is skipped; two concatenated frames decode to the concatenation.Fail(CompressionError)with an offset, never a panic: bad magic, wrong header checksum, flipped content checksum byte, truncated block, output overmaximumSize.std/digestandstd/compressionupdated,skills/regenerated,torb format --checkclean on touched files, FIRST-PARTY.md gap 26 updated (LZ4 frame done, rest named).compiler/src/ir,compiler/src/backendorruntime/.Dependencies
Step 1 (#432), closed. No other dependency.
Commits
Two Conventional Commits:
feat(std): xxHash32 and xxHash64 in std/digestandfeat(std): the LZ4 frame format in std/compression.[loop:torbscript] decided by the loop: ready as filed. Pure TorbScript in std/digest and std/compression, no native, touches the seed: no; xxHash64 may split off as step 2b if the language lacks unsigned 64-bit multiply (measured in the PR, not asked). Acceptance criteria are testable with published vectors. next: implement
[loop:torbscript] claim implement by session:loop-torbscript-20261114 until 2026-11-14T12:00Z
[loop:torbscript] release implement by agent:orion:subagent:fe1cc937-1b10-4b58-bf7e-0d2bb62c83e7
PR: #782 (Refs, not Closes: criterion 3 met with lz4js and spec-built frames, the reference lz4 CLI was unavailable). Local: 92 tests pass, format clean; CI for the rest.
next: waiting (review)