code wiki / (root) / nx_zstd_bits.nx

nx_zstd_bits.nx

buildroot/runtime/nx_zstd_bits.nx

8194 B235 linesdepth 2pulls 2 transitivereach 11 importersview sourcekind librarytopic zstd
docsdependenciesstructsconstsfunctions

about

nx_zstd_bits.nx -- Zstandard's BACKWARD bitstream reader + Huffman weights. The piece between nx_zstd_fse.nx (entropy tables) and a working literals section. Both zstd's Huffman streams and its FSE streams are read BACKWARDS from the end of the buffer, which is unlike every other format in this tree -- DEFLATE, VP8L, FLAC, VP8 and AV1 all read forward. THE STREAM ENDS WITH A MARKER BIT, NOT A LENGTH. The final byte's highest SET bit is a sentinel: it and everything above it is padding, and the real data ends immediately below it. So initialisation must find that bit and start there. A reader that begins at the top of the last byte consumes padding as data and every symbol after it is wrong; a reader that assumes a fixed padding width works only when the payload happens to end byte-aligned. A final byte of ZERO has no marker at all and is corrupt by definition -- it is REFUSED here rather than treated as eight padding bits. BITS ARE PACKED LSB-FIRST WITHIN A BYTE, AND READ HIGH-TO-LOW OVERALL. Those two facts together are the whole trick: absolute bit k lives at data[k >> 3] bit (k & 7) counting from the LSB, and reading walks k DOWNWARD with the first bit taken becoming the MOST significant of the result. THE LAST HUFFMAN WEIGHT IS NOT STORED. Weights encode 2^(w-1) each, and the total must reach the next power of two exactly; the final symbol's weight is whatever completes it. A decoder that reads only the stored weights builds a table missing its last symbol, which decodes most literals correctly and then produces one wrong byte wherever that symbol appears. genealogy_id: zstandard_rfc8878_bitstream lineage_id: nx_zstd_bits_v1 license_tier: ORIGINAL

dependencies 1 imports · 11 importers

nx_syscalls.nx nx_zstd_bits.nx nx_zstd_bits_gate.nx nx_zstd_block.nx nx_zstd_block_gate.nx nx_zstd_fse_dec.nx nx_zstd_fse_dec_gate.nx nx_zstd_huf.nx nx_zstd_huf_gate.nx nx_zstd_lit.nx nx_zstd_lit_gate.nx nx_zstd_seqdec.nx

diagram shows first 10 each side; +0 more imports, +1 more importers in the complete lists below.

imports: nx_syscalls.nx

imported by: nx_zstd_bits_gate.nxnx_zstd_block.nxnx_zstd_block_gate.nxnx_zstd_fse_dec.nxnx_zstd_fse_dec_gate.nxnx_zstd_huf.nxnx_zstd_huf_gate.nxnx_zstd_lit.nxnx_zstd_lit_gate.nxnx_zstd_seqdec.nxnx_zstd_seqdec_gate.nx

structs

38struct NxZstdBits

consts

34const NX_ZB_READER_BYTES: i64 = 40
35const NX_ZB_MAX_WEIGHTS: i64 = 256
36const NX_ZB_MAX_TABLELOG: i64 = 12

functions

45func nx_zb_at(d: *u8, i: i64) -> i64 { return (d[i] as i64) & 255 }
48func nx_zb_highbit8(v: i64) -> i64
64func nx_zstd_bits_init(d: *u8, n: i64) -> *NxZstdBits
78func nx_zstd_bits_remaining(b: *NxZstdBits) -> i64
called by 3: mainmainmain
84func nx_zstd_bits_read(b: *NxZstdBits, nbits: i64) -> i64
106func nx_zstd_bits_peek(b: *NxZstdBits, nbits: i64) -> i64
called by 2: nx_zstd_huf_decodemain calls 1: nx_zb_at
127func nx_zstd_bits_skip(b: *NxZstdBits, nbits: i64) -> i64
141func nx_zstd_weights_direct(d: *u8, n: i64, off: i64, hdr: i64, out: *i64) -> i64
called by 2: mainnx_zstd_block_tree calls 1: nx_zb_at
168func nx_zstd_weights_complete(out: *i64, count: i64) -> i64
202func nx_zstd_weights_tablelog(out: *i64, total_count: i64) -> i64
220func nx_zstd_weights_to_lengths(w: *i64, count: i64, table_log: i64, out_len: *i64) -> i64
called by 1: main