Add HTTP/2 HPACK (RFC 7541) and LHA -lh2- codecs#89
Merged
Conversation
Two requested additions to broaden codec coverage. HPACK (new `hpack` feature, `compcol::hpack`): - Full HTTP/2 header compression per RFC 7541 — N-bit-prefix integers (§5.1), string literals (§5.2), the static table (Appendix A) and a byte-accounted dynamic table with eviction (§4), and every header-field representation (§6.1 indexed; §6.2.1/.2/.3 literals; §6.3 size update). - `HpackEncoder`/`HpackDecoder` carry dynamic-table state across header blocks (HPACK is a stateful header codec, not a byte stream, so it has its own API rather than the Encoder/Decoder traits). - The §5.2 string Huffman primitive (Appendix B table) is also exposed as the `Http2Huffman` codec (name "h2-huffman") on the uniform trait surface, registered in the factory. - Validated byte-for-byte against the RFC 7541 Appendix C worked examples (C.1 integers, C.3 raw + C.4 Huffman request sequences incl. dynamic table evolution), plus decoder error-path rejection (bad index, oversized size update, EOS symbol, bad padding, truncation) and a fuzz target. LHA -lh2- (extends the `lha` feature): - 8 KiB-window LZSS with adaptive (dynamic) Huffman for both literals/lengths and match positions — the latter is what distinguishes lh2 from lh1's fixed position code. Generalizes the adaptive-tree machinery to a runtime alphabet size shared by the 510-symbol char tree and the 14-symbol position-class tree. - Continuous + size-terminated like lh1, so its decoder needs the uncompressed length via DecoderConfig::with_len; registered in factory. - Clean-room from the public dynamic-Huffman description; round-trip validated (no public reference fixture exists — documented as such, matching the other LHA methods). Builds: --all-features and no_std (--no-default-features --features hpack/lha) both clean; cargo test --all-features green; no clippy warnings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- rustfmt the new hpack/lha files (collapse multi-line expressions CI's `cargo fmt --check` rejected). - dynamic_huff module doc: demote `[NC]`/`[NP]` intra-doc links to plain code spans (they are private consts; rustdoc runs with `-D warnings` and rejects public-doc links to private items). - clippy `-D warnings --all-targets`: replace a manual slice-copy loop with the array's Copy in a test, and `repeat().take()` with `repeat_n()`. No behavior change. fmt/doc/clippy/test all clean locally. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the two requested codecs so the crate covers "h2 huffman" and LHA
-lh2-.HTTP/2 HPACK — new
hpackfeature (compcol::hpack)Full RFC 7541 header compression, not just the Huffman primitive:
accounting, §4.4 eviction, and §6.3 size updates.
indexing, §6.2.2 without indexing, §6.2.3 never-indexed, §6.3 size update.
HpackEncoder/HpackDecoderhold dynamic-table state across headerblocks. HPACK works on
(name, value)header lists with per-connectionstate — not a byte stream — so it gets its own API rather than the
Encoder/Decodertraits.Http2Huffmancodec (nameh2-huffman) on the uniform trait surface and isregistered in the factory.
Validation: byte-for-byte against the RFC 7541 Appendix C worked examples —
C.1 integers, C.3 (raw) and C.4 (Huffman) request sequences including dynamic
table evolution, plus the C.4 string vectors. Decoder error paths (index 0,
bad index, oversized size update, decoded EOS, bad Huffman padding, truncation)
are covered, plus a
decoder_h2_huffmanfuzz target.LHA
-lh2-— extends thelhafeature8 KiB-window LZSS with adaptive (dynamic) Huffman for both literals/lengths
and match positions — the dynamic position tree is what separates lh2 from
lh1's fixed position code. The adaptive-tree machinery is generalized to a
runtime alphabet size shared by the 510-symbol char tree and the 14-symbol
position-class tree. Like lh1 it is continuous/size-terminated, so its decoder
takes the length via
DecoderConfig::with_len. Registered in the factory.Validation: clean-room from the public dynamic-Huffman description;
round-trip validated (empty/small/incompressible/repetitive/binary, plus a
far-window match). There is no public
-lh2-reference fixture (no mainstreamtool emits the method), so bit-exact interop with archives in the wild is
best-effort — documented in the module and matching how the other LHA methods
are validated ("own round-trip, no reference fixture").
Checks
cargo build --all-featuresandno_std(--no-default-features --features hpack/--features lha) both clean.cargo test --all-featuresgreen (all suites, incl. 17 hpack unit + 5 hpackintegration + lh2 round-trip/refusal/large-window tests).
cargo clippy --all-features— no warnings.🤖 Generated with Claude Code