pure_zstd 1.1.0
pure_zstd: ^1.1.0 copied to clipboard
A zstd compressor and decompressor written in plain Dart. Reads and writes RFC 8878 frames with no native library and no platform channel, verified against libzstd.
Changelog #
1.1.0 #
An encoder. zstdEncode and ZstdEncoder write RFC 8878 frames, one frame
per call, mirroring the decoder's API. The frames decode under libzstd with
no flags and no overrides.
- Match finding through one hash table plus the last repeated offset, four
bytes minimum, with every match priced against the literal coding it
displaces. A
levelof 1 to 5 trades speed for ratio: greedy, lazy over one or two deferred starts, then chain walks of eight or thirty-two candidates with three-byte matches. The ratio lands between libzstd's level 1 and its level 19, often much nearer 19. - Repeated offsets are emitted whenever an offset matches one of the three recent ones, including the no-literals shift.
- Sequence tables are chosen per block and per alphabet: predefined, RLE, FSE built from the block's own counts, or a repeat of the previous block's, whichever prices smallest.
- Literals are raw, RLE, Huffman, or treeless reusing the previous block's table, whichever is smallest, in one-stream and four-stream form. Code lengths come from package-merge, capped at eleven bits; weights take the direct nibble or the FSE-coded form, whichever is smaller.
- Single-segment frames with an explicit content size up to 128 MiB, and a windowed header above that, so large frames stay inside the window every decoder accepts by default.
- A content checksum by default;
checksum: falsedrops it. - No dictionaries, no streaming, no long-distance matching.
The encoder asserts nothing about its own bytes: every frame must decode to
its input through this package's decoder and through the zstd CLI, over
generic data shapes from prose and JSON logs to base64, binary time series,
and mixed compressible and incompressible segments. 236 tests.
1.0.0 #
First release.
A zstd decompressor in plain Dart. Decompression only, native platforms only, one frame per call.
- Decodes RFC 8878 frames: raw, RLE and compressed blocks; raw, RLE, compressed and treeless literals in one-stream and four-stream form; Huffman weights in both the direct nibble and FSE-coded forms; predefined, RLE, FSE and repeat sequence tables for all three symbols; repeated offsets including the no-literals shift; multi-block frames reusing an earlier block's tables.
- Verifies the content checksum when a frame carries one, with XXH64 in
lib/src/xxhash.dart. - Refuses dictionaries, several frames in one buffer, and any input left over after a frame.
- Bounds what a frame header can make it allocate.
ZstdDecodertakes amaxOutputSize, 64 MiB by default, and a caller passingexpectedSizegets an exact check against the frame's own declared size. - Every failure is a
ZstdException.
Correctness is measured against libzstd through pyzstd rather than against expectations written by hand: 2,615 blocks of real elevation data across 32 containers, plus a committed corpus of 23 cases covering the format branches that real data never reaches. 131 tests.
Roughly four times slower than native zstd. On a Pixel 10 Pro XL, profile AOT, a 128 KiB block decodes in 0.414 ms, which is 302 MB/s.