Repository navigation
fix(decoder): hand out every decoded byte, not only what left the window - #605
Conversation
The streaming paths handed the caller only decoded bytes that had left the window, so until a frame ended its newest window of output stayed inside the decoder. A frame kept open and flushed, as rsync keeps one zstd frame per session and flushes it after every file, delivered none of its last window, and every file failed rsync's checksum. - The decode buffer keeps a delivered mark: a read copies out every byte not handed out yet, oldest first, as far as the target takes, hashing it as it goes; the window stays as history, and only bytes that are both handed out and outside the window are let go. Upstream copies each decoded block out of its window buffer the same way (zstd_decompress.c, zdss_flush). - decode_from_to, the Read adapter, collect, collect_to_writer, can_collect, the caller-workspace decoder and ZSTD_decompressStream hand out output this way; history a caller inserted or primed itself counts as handed out. - StreamingDecoder takes a frame's checksum in the call that hands over the last of its output, so the source stands past the frame, as upstream reads the checksum once the last block is flushed. - decode_loop_z000033 gains a `read` mode that decodes through Read in 64 KiB pieces. Regression tests: a_session_flushed_per_file_decodes_file_by_file (the rsync calling pattern through the C ABI), a_flushed_frame_in_progress_hands_over_everything_so_far, decode_from_to_hands_over_an_unfinished_frame. Closes #604
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
## 🤖 New release * `structured-zstd`: 0.2.2 -> 0.2.3 <details><summary><i><b>Changelog</b></i></summary><p> <blockquote> ## [0.2.3](v0.2.2...v0.2.3) - 2026-10-19 ### Added - *(c-api)* the experimental zstd.h and zdict.h surface ([#602](#602)) ### Fixed - *(decoder)* hand out every decoded byte, not only what left the window ([#605](#605)) - *(encoder)* take table pointers from the table, not a slice ([#598](#598)) ### Testing - *(ci)* prove the drop-in claim against upstream's suites, the reference CLI and real consumers ([#610](#610)) - run the lsm tests in CI and fix the one that rotted ([#608](#608)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/release-plz/release-plz/). Co-authored-by: sw-release-bot[bot] <255865126+sw-release-bot[bot]@users.noreply.github.com>
Summary
--compress-choice=zstdwith this library in place of libzstd: rsync keeps one frame per session and flushes it after every file, and every file used to fail its checksum.Changes
DecodeBufferkeeps a delivered mark: reads copy out every undelivered byte oldest first, hashing as they go; the window stays as history, and only bytes both delivered and outside the window are released (as upstream copies each decoded block out inzdss_flush).decode_from_to, theReadadapter,collect,collect_to_writer,can_collect, the caller-workspace decoder andZSTD_decompressStreamdeliver output this way; inserted or primed history counts as delivered.StreamingDecodertakes a frame's checksum in the call that hands over the last of its output, so the source stands past the frame.decode_loop_z000033gains areadmode (decode throughReadin 64 KiB pieces).Testing
Readadapter anddecode_from_to; fmt, clippy, nextest (default and caller-workspace), C ABI tests, doctests and rustdoc pass.--compress-choice=zstdwith the library preloaded on both ends transfers files that pass rsync's verification on Linux x86_64; the same run fails on main.readpath on x86_64 (bench profile, interleaved, with a control arm): no regression.Closes #604
Summary by CodeRabbit