ESE format modules¶
7-bit ASCII (0x1)¶
ntcompress.ese.sevenbit_ascii
¶
COMPRESS_7BITASCII (0x1) -- 7-bit ASCII packing for ESE records.
Authority: ErrCompress7BitAscii_ (compression.cxx:1168-1387) and
ErrDecompress7BitAscii_ (:2113-2185).
7-bit Unicode (0x2)¶
ntcompress.ese.sevenbit_unicode
¶
COMPRESS_7BITUNICODE (0x2) -- 7-bit Unicode packing for ESE records.
Identical bitstream to 7BITASCII; only the source stride (2 bytes) and the
0x00 high-byte re-emission on decode differ. Authority:
ErrCompress7BitUnicode_ (compression.cxx:1390-1504) and
ErrDecompress7BitUnicode_ (:2188-2272).
decompress(blob: Buffer) -> bytes
¶
Unpack a 7BITUNICODE cell to UTF-16LE plaintext bytes.
Per ErrDecompress7BitUnicode_ (compression.cxx:2188-2272): emit each
unpacked 7-bit value followed by a 0x00 high byte (:2251-2255) to
reconstruct the little-endian code units.
compress(data: Buffer) -> bytes
¶
Pack 7-bit-clean UTF-16LE text into a framed 7BITUNICODE cell.
Per ErrCompress7BitUnicode_ (compression.cxx:1390-1504), with the
applicability rules of Calculate7BitCompressionScheme_ (:1007-1118):
the input must be an even number of bytes, every code unit must be
<= 0x007f, and the result must beat the plaintext.
decompressed_size(blob: Buffer) -> int
¶
Return the plaintext byte length of a 7BITUNICODE cell without decoding.
The exact ESE formula: cwTotal = ((Cb - 2) * 8 + cbitFinal) // 7 code
units, times sizeof(WORD) (compression.cxx:2210-2216).
XPRESS (0x3)¶
ntcompress.ese.xpress
¶
COMPRESS_XPRESS (0x3) -- ESE record framing over MS-XCA Plain LZ77.
Implements the ESE scheme COMPRESS_XPRESS: a 3-byte header (scheme byte + u16
little-endian uncompressed size) wrapping a raw MS-XCA Plain LZ77 stream. The raw
codec itself lives in :mod:ntcompress.ntdll.xpress so it can be reused outside ESE;
this module only adds and strips the ESE frame.
Frame layout, per the MIT ESE source (ErrCompressXpress_,
compression.cxx:1507-1568; ErrDecompressXpress_, :2275-2347)::
offset 0: u8 scheme byte = COMPRESS_XPRESS << 3 = 0x18 (compression.cxx:1551)
offset 1..2: u16 uncompressed size, little-endian (compression.cxx:1549-1552)
offset 3..: raw Plain LZ77 stream ([MS-XCA] §2.3 / §2.4)
The u16 size field caps a single cell's plaintext at 65535 bytes
(Assert( data.Cb() <= wMax ), compression.cxx:1518), and ESE stores a compressed
cell only when it is strictly smaller than the plaintext (errRECCannotCompress
otherwise, compression.cxx:1541-1545). Dispatch is on the top 5 bits of byte 0
(bIdentifier = bHeader >> 3, compression.cxx:2294), not the whole byte, so a
hypothetical nonzero flag bit does not misroute.
HEADER_SIZE: Final = 3
module-attribute
¶
ESE XPRESS frame size: sizeof(BYTE) + sizeof(WORD) (compression.cxx:1528, :2300).
MAX_UNCOMPRESSED: Final = 65535
module-attribute
¶
Largest plaintext one cell can record in its u16 size field (compression.cxx:1518).
decompress(blob: Buffer, *, verify: bool = True) -> bytes
¶
Decode an XPRESS (0x3) cell to plaintext.
Strips the 3-byte frame and decodes the remainder per [MS-XCA] §2.4, the
Python equivalent of ErrDecompressXpress_ handing pb + cbHeader to
XpressDecode (compression.cxx:2301, :2316-2322).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blob
|
Buffer
|
The framed cell, scheme byte included. |
required |
verify
|
bool
|
When True, require the decoded length to equal the header's declared size. The declared size always caps the decode regardless of this flag. |
True
|
Raises:
| Type | Description |
|---|---|
DecompressionError
|
Truncated or mis-schemed frame, an invalid payload
stream, a decode that overruns the declared size, or (with
|
compress(data: Buffer) -> bytes
¶
Encode plaintext into an XPRESS (0x3) cell.
Mirrors ErrCompressXpress_ (compression.cxx:1507-1568): encode the
payload per [MS-XCA] §2.3, prepend the 0x18 scheme byte and the u16 LE
plaintext size, and refuse to "compress" unless that saves space.
Raises:
| Type | Description |
|---|---|
CompressionError
|
The plaintext exceeds the 65535 bytes the u16 size field can record (compression.cxx:1518). |
IncompressibleError
|
The framed cell would not be strictly smaller than
the plaintext -- ESE's |
decompressed_size(blob: Buffer) -> int
¶
Return the u16 uncompressed size from the frame, without decoding (compression.cxx:2290-2291).
XPRESS9 (0x5)¶
ntcompress.ese.xpress9
¶
COMPRESS_XPRESS9 (0x5) -- pure-Python XPRESS9 codec.
XPRESS9 has no public byte-format specification: [MS-XCA] does not cover it, and
the authority is the MIT-licensed ESE C codec in dev/ese/src/_xpress9/. This
module is an ATTRIBUTED PORT of that codec (see THIRD-PARTY-NOTICES.md), not
clean-room work, so every constant and rule below cites its C file:line.
The on-disk layout has two layers:
- ESE outer record header (
Xpress9Header, compression.cxx:515-521, 5 bytes): scheme byte(COMPRESS_XPRESS9 << 3) == 0x28(compression.cxx:1757) followed by a u32 LE CRC-32C of the plaintext (compression.cxx:1758, verified after decompression at compression.cxx:2461-2462). - One or more Xpress9 blocks, each a 32-byte header (
LZ77_BLOCK_HEADER, Xpress9Internal.h:972-984, magic0x4E86D72A, itself CRC-32C protected) followed by a single LSB-first bitstream holding: optional MTF (repeated-offset) initial state, two serialized canonical-Huffman code-length tables (short-symbol alphabet of 704, long-length alphabet of 256), and the LZ77 token stream with Elias-gamma offset coding (Xpress9Lz77Dec.i). ESE always writes the fixed "Cosmos Level 6" parameters MTF=4 / PtrMin=4 / MtfMin=2 / window 2**16 (compression.cxx:1696-1706), but this port handles every legal parameter combination like the C decoder does.
The encoder is a port of the C codec's lazy match finder (Xpress9Lz77EncPass1.i
with LAZY_MATCH_EVALUATION, DEEP_LOOKUP=1): hash-chain LZ77 with 4-entry MTF
support, 2-position lookahead, and Mode 0/1 Huffman table selection. The encoder
produces byte-identical output to the MIT ESE C reference encoder, excluding only
the non-deterministic session signature (CRC32(__rdtsc()), Xpress9EncLz77.c:1128).
Note: ntdll format 0x0005 is NOT XPRESS9 -- it has block magic 0xC039E510 (vs
XPRESS9's 0x4E86D72A) and is an entirely different, undocumented algorithm.
Known deviations from the C decoder, all only reachable with corrupt input:
* Match offsets are validated against the bytes decoded so far in the session
(Xpress9Lz77Dec.i:248), not additionally against the C decoder's internal buffer
geometry of about 1.5x the window size (Xpress9DecLz77.c:223), so a hand-crafted
stream may reference slightly further back than a real decoder buffer would allow.
* A degenerate single-symbol Huffman table whose codeword is longer than 15 bits is
decoded arithmetically here, where the C table builder's 4-bit skip field would
silently overflow (Xpress9DecHuffman.c:360-372). The encoder emits neither case.
* ESE's ErrDecompressXpress9_ performs a single fetch (compression.cxx:2437-2449),
so it decodes the first block and silently ignores any trailing bytes; this port
walks the whole session, so trailing bytes must parse as further valid blocks or the
cell is rejected. ESE itself never writes trailing bytes (compression.cxx:1759).
HEADER_SIZE: Final = 5
module-attribute
¶
Size of the packed Xpress9Header: scheme byte + u32 LE plaintext CRC-32C ("Reserve 5 bytes for the header", compression.cxx:1691).
BLOCK_HEADER_SIZE: Final = 32
module-attribute
¶
Size of LZ77_BLOCK_HEADER: 8 x u32 LE (Xpress9Internal.h:972-984).
XPRESS9_MAGIC: Final = 1317459754
module-attribute
¶
XPRESS9_MAGIC, word [0] of every block header (Xpress9Internal.h:970).
Xpress9BlockHeader(orig_size: int, comp_size_bits: int, huffman_table_bits: int, window_size_log2: int, mtf_entry_count: int, ptr_min_match_length: int, mtf_min_match_length: int, session_signature: int, block_index: int)
dataclass
¶
Parsed and validated 32-byte LZ77_BLOCK_HEADER (Xpress9Internal.h:972-995).
Attributes:
| Name | Type | Description |
|---|---|---|
orig_size |
int
|
|
comp_size_bits |
int
|
|
huffman_table_bits |
int
|
flags bits 0..12 -- bits spent on the MTF initial state plus both serialized Huffman tables (Xpress9DecLz77.c:656, :797-802). |
window_size_log2 |
int
|
flags bits 13..15 plus 16 (Xpress9DecLz77.c:665). |
mtf_entry_count |
int
|
flags bits 16..17 doubled: 0, 2 or 4 (Xpress9DecLz77.c:659). |
ptr_min_match_length |
int
|
flags bit 18 plus 3 (Xpress9DecLz77.c:666). |
mtf_min_match_length |
int
|
flags bit 19 plus 2 (Xpress9DecLz77.c:667). |
session_signature |
int
|
|
block_index |
int
|
|
compress(data: Buffer) -> bytes
¶
Encode plaintext into a framed XPRESS9 cell.
Mirrors ErrCompressXpress9_ (compression.cxx:1686-1759): encode the
payload as XPRESS9 block(s), prepend the 0x28 scheme byte and a u32 LE
CRC-32C of the plaintext, and refuse to "compress" unless that saves space.
Raises:
| Type | Description |
|---|---|
CompressionError
|
The input is empty. |
IncompressibleError
|
The framed cell would not be strictly smaller than
the plaintext -- ESE's |
decompress(blob: Buffer, *, verify: bool = True) -> bytes
¶
Decode a framed XPRESS9 cell to its plaintext.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blob
|
Buffer
|
The framed cell: scheme byte 0x28, u32 LE plaintext CRC-32C, then the raw Xpress9 block(s). |
required |
verify
|
bool
|
When True, check the header's plaintext CRC-32C against the
decoded output, as |
True
|
Raises:
| Type | Description |
|---|---|
DecompressionError
|
Truncated or corrupt frame, block header, Huffman table, or token stream. |
IntegrityError
|
|
decompressed_size(blob: Buffer) -> int
¶
Return the plaintext size recorded in the block header(s), without decoding.
The 5-byte record header carries no size (unlike XPRESS10 and LZ4), so the
size comes from m_uOrigSizeBytes -- the C decoder's fast path for a
zero-length fetch (Xpress9DecLz77.c:718-726), summed across blocks.
parse_block_header(payload: Buffer, offset: int = 0) -> Xpress9BlockHeader
¶
Parse and validate one block header, mirroring Xpress9DecoderFetchDecompressedData (Xpress9DecLz77.c:607-716).
Checks, in the C decoder's order: magic, reserved word zero, header CRC-32C over
the first seven words seeded by the (zero) reserved word (Xpress9DecLz77.c:638;
Xpress9Crc32 in Xpress9Misc.c:229-247 is plain CRC-32C for a zero seed),
reserved flag bits, MTF entry count, and that the compressed bit size exceeds
the header-plus-tables overhead.
Raises:
| Type | Description |
|---|---|
DecompressionError
|
The buffer is too short or any header check fails. |
XPRESS10 (0x6)¶
ntcompress.ese.xpress10
¶
COMPRESS_XPRESS10 (0x6) -- ESE framing over the LZ4 block payload format.
The XPRESS10 record carries a packed 15-byte header (scheme byte, u16 LE uncompressed size, u32 LE CRC-32C over the plaintext, u64 LE CRC-64/NVME over the compressed payload) with the raw XP10 payload starting at offset 15.
The XP10 payload is the standard LZ4 block format -- the same codec used by ESE
scheme 0x7 (COMPRESS_LZ4) and by RtlCompressBufferXp10 / RtlDecompressBufferXp10
in ntdll.dll. Verified by decoding the ntdll format 0x0006 gold vector (52 bytes
for a 4096-byte A-Z pattern) with :func:~ntcompress.ese.lz4.decompress_block,
producing byte-identical plaintext. The only differences from COMPRESS_LZ4 are the
header size (15 vs 3 bytes), the presence of CRC-32C over plaintext AND CRC-64/NVME
over the compressed payload, and the scheme id (0x6 vs 0x7).
Authority: compression.cxx:523-532 (packed Xpress10Header, C_ASSERT
size 15 at :1940/:2503); scheme check (byte >> 3) == COMPRESS_XPRESS10
(compression.cxx:2513); CRC-32C over plaintext (os/encrypt.cxx:147-184);
CRC-64/NVME over payload, reflected poly 0x9A6C9329AC4BC9B5
(_xpress10/xpress10sw.cxx:34-59). [MS-XCA] does not cover XPRESS10.
HEADER_SIZE: Final = 15
module-attribute
¶
Size of the packed Xpress10Header (C_ASSERT at compression.cxx:1940).
MAX_UNCOMPRESSED: Final = 65535
module-attribute
¶
Maximum plaintext size for a single XPRESS10 cell (u16 ceiling).
Xpress10Header(uncompressed_size: int, plaintext_crc32c: int, payload_crc64: int)
dataclass
¶
Parsed 15-byte Xpress10Header (compression.cxx:523-532).
Attributes:
| Name | Type | Description |
|---|---|---|
uncompressed_size |
int
|
|
plaintext_crc32c |
int
|
|
payload_crc64 |
int
|
|
parse_header(blob: Buffer) -> Xpress10Header
¶
Parse and validate the leading 15-byte XPRESS10 header of a framed cell.
Mirrors the entry checks of ErrDecompressXpress10_ (compression.cxx:2503,
:2513): the buffer must hold the full header, and the top five bits of byte 0
must carry COMPRESS_XPRESS10.
Raises:
| Type | Description |
|---|---|
DecompressionError
|
The buffer is shorter than 15 bytes, or its format id is not XPRESS10. |
decompress(blob: Buffer, *, verify: bool = True) -> bytes
¶
Decompress an XPRESS10-framed cell.
Strips the 15-byte header, optionally verifies both CRC checksums, and decodes the LZ4 block payload.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blob
|
Buffer
|
The framed cell, including the 15-byte header. |
required |
verify
|
bool
|
When True, validate the CRC-32C over plaintext and CRC-64/NVME over the compressed payload. |
True
|
Raises:
| Type | Description |
|---|---|
DecompressionError
|
Truncated buffer, wrong scheme byte, or LZ4 decode failure. |
IntegrityError
|
|
compress(data: Buffer) -> bytes
¶
Compress data into an XPRESS10-framed cell.
Encodes the plaintext as an LZ4 block, computes both CRC checksums, and prepends the 15-byte header.
Raises:
| Type | Description |
|---|---|
CompressionError
|
Plaintext exceeds the u16 size limit (65535 bytes). |
IncompressibleError
|
Compressed cell is not strictly smaller than plaintext. |
decompressed_size(blob: Buffer) -> int
¶
Return mle_cbUncompressed from the header (compression.cxx:2518-2524).
LZ4 (0x7)¶
ntcompress.ese.lz4
¶
COMPRESS_LZ4 (0x7) -- ESE record framing over the standard LZ4 block format.
ESE does not define its own codec here: it links the reference liblz4 and calls
LZ4_compress_default (compression.cxx:2085) / LZ4_decompress_safe_partial
(compression.cxx:2677), so the payload is the standard LZ4 block format -- no LZ4
frame, no magic, no checksum, and no stored size. The plaintext length lives
out-of-band in the 3-byte ESE Lz4Header (compression.cxx:534-539): scheme byte
COMPRESS_LZ4 << 3 = 0x38, then a u16 little-endian uncompressed size. This
module implements the block format directly in Python -- no lz4 dependency.
Block format (lz4_Block_format.md): each sequence is a token byte (high nibble =
literal length, low nibble = match length), optional 0xFF-continuation length
bytes, the literals, a 2-byte little-endian match offset, and optional match-length
continuation bytes. minmatch is 4 (the stored nibble is length - 4), offset 0
is invalid, the maximum offset is 65535, matches may overlap their own output
(RLE-style), the last sequence is literals only, the last 5 bytes of a block are
literals, and the last match starts at least 12 bytes before the end.
The encoder is a greedy hash-table matcher that honours those end-of-block
invariants; it produces valid blocks that any conformant decoder (including liblz4)
accepts, but not necessarily the byte-identical output of LZ4_compress_default.
Authority: ESE compression.cxx:2070-2109 (ErrCompressLz4_) and :2643-2699
(ErrDecompressLz4_) for the framing; lz4/lz4 doc/lz4_Block_format.md for the
payload. [MS-XCA] does not cover LZ4.
HEADER_SIZE: Final = 3
module-attribute
¶
Size of the packed Lz4Header (C_ASSERT at compression.cxx:2083 / :2654).
MAX_UNCOMPRESSED: Final = 65535
module-attribute
¶
mle_cbUncompressed is a WORD, and ESE routes only cells of at most wMax bytes to LZ4 (compression.cxx:2080, :2761).
MIN_MATCH: Final = 4
module-attribute
¶
minmatch: the low token nibble stores match_length - 4 (lz4_Block_format.md).
MAX_OFFSET: Final = 65535
module-attribute
¶
Largest encodable back-reference distance; "65536 and beyond cannot be coded" (lz4_Block_format.md).
Lz4Header(uncompressed_size: int)
dataclass
¶
Parsed 3-byte Lz4Header (compression.cxx:534-539).
Attributes:
| Name | Type | Description |
|---|---|---|
uncompressed_size |
int
|
|
parse_header(blob: Buffer) -> Lz4Header
¶
Parse and validate the leading 3-byte LZ4 header of a framed cell.
Mirrors the entry checks of ErrDecompressLz4_: a cell shorter than the
header is rejected (compression.cxx:2656-2660), and the top five bits of byte 0
must carry COMPRESS_LZ4 (compression.cxx:2664-2667).
Raises:
| Type | Description |
|---|---|
DecompressionError
|
The buffer is shorter than 3 bytes, or its format id is not LZ4. |
decompress_block(payload: Buffer, uncompressed_size: int) -> bytes
¶
Decode a headerless LZ4 block to exactly uncompressed_size bytes.
The block format carries no size, so the target must be supplied out-of-band --
for an ESE cell it comes from Lz4Header.mle_cbUncompressed. Matching ESE's
LZ4_decompress_safe_partial(..., targetOutputSize=cbDataMax,
dstCapacity=cbDataMax) call (compression.cxx:2677-2682), decoding stops the
moment the target size has been produced, even mid-sequence; any further payload
bytes are ignored. Unlike ESE release builds (which only Assert the decoded
count, compression.cxx:2688), a block that runs out of input before reaching
the target is rejected here rather than returned short.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
Buffer
|
The raw LZ4 block bytes (for an ESE cell, the bytes from offset 3). |
required |
uncompressed_size
|
int
|
Exact plaintext length to produce. |
required |
Raises:
| Type | Description |
|---|---|
DecompressionError
|
Truncated or corrupt block (EOF mid-sequence, zero
offset, offset pointing before the start of the output, or the block
ending before |
compress_block(data: Buffer) -> bytes
¶
Encode data as a headerless LZ4 block.
Greedy matcher over a hash table of 4-byte substrings, honouring every
end-of-block invariant from lz4_Block_format.md: matches are at least
MIN_MATCH bytes, reach back at most MAX_OFFSET, start at least 12 bytes
before the end, and stop 5 bytes short of it so the block ends in a
literals-only sequence. The output decodes with any conformant LZ4 block
decoder; it is not guaranteed byte-identical to LZ4_compress_default.
decompress(blob: Buffer, *, verify: bool = True) -> bytes
¶
Decode an LZ4 (0x7) cell to its plaintext.
Port of ErrDecompressLz4_ (compression.cxx:2643-2699): validate the
header, then decode the block at offset 3 up to the out-of-band
mle_cbUncompressed target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blob
|
Buffer
|
The framed cell, including the 3-byte header. |
required |
verify
|
bool
|
Accepted for interface consistency; the LZ4 frame carries no checksum, so there is nothing extra to verify. |
True
|
Raises:
| Type | Description |
|---|---|
DecompressionError
|
Truncated buffer, wrong scheme byte, or a corrupt block payload. |
compress(data: Buffer) -> bytes
¶
Encode plaintext into a framed LZ4 (0x7) cell.
Port of ErrCompressLz4_ (compression.cxx:2070-2109): compress into a
standard LZ4 block behind a 3-byte header carrying 0x38 and the u16 LE
plaintext size (compression.cxx:2104-2105).
Raises:
| Type | Description |
|---|---|
CompressionError
|
|
IncompressibleError
|
The compressed payload plus the 3-byte header would
not be smaller than the plaintext -- ESE refuses to store such cells
( |
decompressed_size(blob: Buffer) -> int
¶
Return mle_cbUncompressed from the header (compression.cxx:2669-2670).
SCRUB (0x4)¶
ntcompress.ese.scrub
¶
COMPRESS_SCRUB (0x4) -- a data-erasure marker, not a codec.
SCRUB does not compress anything: database maintenance and repair overwrite an
orphaned long-value chunk with a known fill pattern and tag it with this scheme so
later reads can detect the erasure instead of mis-decoding it. There is no plaintext
to recover, so this module is never registered as a codec -- the dispatcher raises
:class:~ntcompress.exceptions.ScrubDetectedError for scheme 0x4. What lives
here are helpers to recognize a scrub cell (:func:is_scrub,
:func:scrub_fill_byte, :func:parse_scrub) and to produce one
(:func:make_scrub), mirroring CDataCompressor::ErrScrub.
Authority: ESE compression.cxx:1571-1590 (write) and :2350-2391 (recognize);
fill-pattern constants in dev/ese/src/inc/daedef.hxx:1063-1072.
ScrubFill
¶
Bases: IntEnum
The two chSCRUB* fill bytes that reach a 0x4 compression cell.
Only long-value-chunk scrubbing writes through the compression-cell path
(ErrRECScrubLVChunk, compression.cxx:3007-3014); the other chSCRUB*
page/record fills are written directly into page bytes and never appear here.
Values from daedef.hxx:1064 and :1069.
ScrubRecord(erased_length: int, fill_byte: int | None, known_fill: bool)
dataclass
¶
A recognized SCRUB cell, described for forensic reporting.
Captures what ErrDecompressScrub_ (compression.cxx:2350-2391) inspects:
the erased length (scrubbing is in place, so it equals the original chunk
length) and the uniform fill byte, flagged when it matches a known
chSCRUB* LV-chunk value. Retail ESE accepts any fill, so known_fill
is informational, not a validity gate.
erased_length: int
instance-attribute
¶
Total cell length in bytes, header included; the original chunk length.
fill_byte: int | None
instance-attribute
¶
The uniform fill after the header, or None if absent (1-byte cell) or non-uniform.
known_fill: bool
instance-attribute
¶
True when fill_byte is one of the two documented :class:ScrubFill values.
is_scrub(blob: Buffer) -> bool
¶
Report whether a cell's leading byte carries the SCRUB format id.
Exists so callers can screen cells before dispatching, instead of catching
:class:~ntcompress.exceptions.ScrubDetectedError. Matches the decode
dispatch test bIdentifier == COMPRESS_SCRUB (compression.cxx:2852, 2865).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blob
|
Buffer
|
A (possibly empty) framed ESE cell. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True iff the buffer is non-empty and |
scrub_fill_byte(blob: Buffer) -> int | None
¶
Return the uniform fill byte of a scrub cell's erased region.
ErrScrub memsets everything after the header to one byte
(compression.cxx:1587), so a well-formed cell has a single fill value. This
surfaces it for forensic reporting (which scrubber wrote the cell).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blob
|
Buffer
|
A framed cell; typically one for which :func: |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
The fill byte repeated over |
int | None
|
empty (a 1-byte cell, legal per compression.cxx:3556-3561) or not uniform. |
parse_scrub(blob: Buffer) -> ScrubRecord
¶
Describe a SCRUB cell as a :class:ScrubRecord.
The read-side counterpart of :func:make_scrub. ErrDecompressScrub_ runs its
checks only in DEBUG builds (compression.cxx:2361-2389); this bundles the scheme-id
check and the uniform-fill read into one immutable record for callers that want
more than a boolean. It deliberately does not enforce the low-3-flag-bits-zero
condition, which ESE states as a soft Expected it tolerates (:2370), not an
assert, so a cell with nonzero flag bits still parses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blob
|
Buffer
|
A framed cell whose format id must be SCRUB. |
required |
Returns:
| Type | Description |
|---|---|
ScrubRecord
|
The erased length, fill byte, and whether the fill is a known |
ScrubRecord
|
class: |
Raises:
| Type | Description |
|---|---|
DecompressionError
|
The buffer is empty or not a SCRUB cell. |
make_scrub(length: int, fill: int = ScrubFill.DB_MAINT_LV_CHUNK) -> bytes
¶
Build a scrub cell of a given total length, as ErrScrub would in place.
Mirrors CDataCompressor::ErrScrub (compression.cxx:1571-1590): byte 0 is
COMPRESS_SCRUB << 3 = 0x20 and the remaining length - 1 bytes are the
fill. A 1-byte cell is legal and is just the header.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
length
|
int
|
Total cell size in bytes (the chunk length being erased), >= 1. |
required |
fill
|
int
|
The fill byte, 0-255; defaults to |
DB_MAINT_LV_CHUNK
|
Returns:
| Type | Description |
|---|---|
bytes
|
The framed scrub cell. |
Raises:
| Type | Description |
|---|---|
CompressionError
|
|