ntcompress 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ntcompress/__init__.py ADDED
@@ -0,0 +1,20 @@
1
+ """Pure-Python codecs for Microsoft ESE record-compression and Windows ntdll compression formats.
2
+
3
+ ``ntcompress`` compresses and decompresses all ESE record schemes (7-bit ASCII/Unicode,
4
+ XPRESS, SCRUB, XPRESS9, XPRESS10, LZ4) and all ntdll ``RtlCompressBuffer`` formats
5
+ (LZNT1, XPRESS, XPRESS_HUFF, Compact XPRESS9, XP10, DEFLATE, ZLIB). Compress output is
6
+ verified byte-identical to ``esent.dll`` and ``ntdll.dll`` across 16 Windows builds. No
7
+ runtime dependencies beyond the standard library.
8
+
9
+ ESE codecs live under :mod:`ntcompress.ese`; ntdll standalone codecs under
10
+ :mod:`ntcompress.ntdll`.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from importlib.metadata import PackageNotFoundError, version
16
+
17
+ try:
18
+ __version__ = version("ntcompress")
19
+ except PackageNotFoundError: # pragma: no cover - source checkout without install metadata
20
+ __version__ = "0.0.0"
ntcompress/_types.py ADDED
@@ -0,0 +1,8 @@
1
+ """Shared type aliases used across both the ESE and ntdll subpackages."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TypeAlias
6
+
7
+ Buffer: TypeAlias = bytes | bytearray | memoryview
8
+ """Any read-only bytes-like input accepted by the codecs."""
@@ -0,0 +1,216 @@
1
+ """ESE (Extensible Storage Engine) record-compression formats.
2
+
3
+ Provides both Shape A (enum dispatch) and Shape B (direct module import) APIs for
4
+ every ESE record-compression scheme. The ``Format`` enum values are the 5-bit scheme
5
+ IDs extracted from the first byte of a compressed ESE cell, matching the
6
+ ``CDataCompressor::COMPRESSION_SCHEME`` constants in the MIT ESE source.
7
+
8
+ Shape A (enum dispatch)::
9
+
10
+ import ntcompress.ese
11
+ compressed = ntcompress.ese.compress(data, ntcompress.ese.Format.XPRESS)
12
+ plain = ntcompress.ese.decompress(compressed) # auto-detects format
13
+
14
+ Shape B (direct module)::
15
+
16
+ from ntcompress.ese import xpress
17
+ compressed = xpress.compress(data)
18
+ plain = xpress.decompress(compressed)
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from enum import IntEnum
24
+ from typing import TYPE_CHECKING, Final
25
+
26
+ from ntcompress.ese._registry import _get, _register
27
+ from ntcompress.exceptions import (
28
+ CompressionError,
29
+ DecompressionError,
30
+ FormatUnavailableError,
31
+ ScrubDetectedError,
32
+ )
33
+
34
+ if TYPE_CHECKING:
35
+ from ntcompress._types import Buffer
36
+
37
+
38
+ # --- Header bit layout ---
39
+
40
+ _SCHEME_SHIFT: Final = 3
41
+ """Bit offset of the 5-bit format id within the header byte (compression.cxx:2003)."""
42
+
43
+ _FLAG_MASK: Final = 0b0000_0111
44
+ """Mask selecting the low 3 format-specific flag bits of the header byte."""
45
+
46
+
47
+ class Format(IntEnum):
48
+ """ESE record-compression format identifiers.
49
+
50
+ Values are the 5-bit scheme IDs extracted from the first byte of a compressed
51
+ ESE cell. See ``CDataCompressor::COMPRESSION_SCHEME`` in the MIT-licensed ESE
52
+ source (``compression.cxx:504-512``).
53
+ """
54
+
55
+ NONE = 0x00
56
+ """Sentinel -- uncompressed cell, no compression header."""
57
+
58
+ SEVEN_BIT_ASCII = 0x01
59
+ """7-bit ASCII packing (compression.cxx:1168-1387)."""
60
+
61
+ SEVEN_BIT_UNICODE = 0x02
62
+ """7-bit Unicode packing over UTF-16LE code units (compression.cxx:1390-1504)."""
63
+
64
+ XPRESS = 0x03
65
+ """Plain LZ77 ([MS-XCA] §2.1) with 3-byte ESE frame (compression.cxx:1507-1568)."""
66
+
67
+ SCRUB = 0x04
68
+ """Erase marker -- not a compression format. Use :mod:`ntcompress.ese.scrub`."""
69
+
70
+ XPRESS9 = 0x05
71
+ """LZ77+Huffman9 with ESE frame (compression.cxx:1686-1759)."""
72
+
73
+ XPRESS10 = 0x06
74
+ """LZ4 block + CRC-32C/CRC-64 integrity (compression.cxx:1935-2064)."""
75
+
76
+ LZ4 = 0x07
77
+ """Raw LZ4 block with 3-byte ESE frame (compression.cxx:2070-2109)."""
78
+
79
+ MAXIMUM = 0x1F
80
+ """Sentinel -- upper bound of the 5-bit scheme space, not a real format."""
81
+
82
+
83
+ # --- First-byte helpers ---
84
+
85
+
86
+ def format_id(first_byte: int) -> int:
87
+ """Extract the 5-bit format ID from an ESE cell's header byte.
88
+
89
+ Returns ``first_byte >> 3`` (0-31). Callers map this to a :class:`Format` member.
90
+ """
91
+ return first_byte >> _SCHEME_SHIFT
92
+
93
+
94
+ def format_flags(first_byte: int) -> int:
95
+ """Extract the 3 format-specific flag bits from an ESE cell's header byte.
96
+
97
+ Returns ``first_byte & 0x7``. Meaning is format-specific.
98
+ """
99
+ return first_byte & _FLAG_MASK
100
+
101
+
102
+ def header_byte(fmt: Format, flags: int = 0) -> int:
103
+ """Build a record header byte from a format id and optional flag bits.
104
+
105
+ Returns ``(fmt << 3) | (flags & 0x7)``.
106
+ """
107
+ return (fmt << _SCHEME_SHIFT) | (flags & _FLAG_MASK)
108
+
109
+
110
+ # --- Shape A dispatch ---
111
+
112
+
113
+ def _format_of(blob: Buffer) -> Format:
114
+ """Resolve a buffer's leading byte to a :class:`Format`, or raise."""
115
+ if len(blob) == 0:
116
+ msg = "cannot read a compression format from an empty buffer"
117
+ raise DecompressionError(msg)
118
+ raw = format_id(blob[0])
119
+ try:
120
+ fmt = Format(raw)
121
+ except ValueError:
122
+ msg = f"unknown ESE compression format id 0x{raw:x}"
123
+ raise DecompressionError(msg) from None
124
+ if fmt is Format.MAXIMUM:
125
+ msg = f"Format.MAXIMUM (0x{raw:x}) is a sentinel value, not a compression format"
126
+ raise DecompressionError(msg)
127
+ return fmt
128
+
129
+
130
+ def compress(data: Buffer, fmt: Format) -> bytes:
131
+ """Encode plaintext into a framed ESE cell using the specified format.
132
+
133
+ Args:
134
+ data: The plaintext to compress.
135
+ fmt: The ESE compression format to use.
136
+
137
+ Raises:
138
+ CompressionError: The format is a sentinel (NONE, SCRUB, MAXIMUM), or the
139
+ input cannot be encoded by the requested format.
140
+ FormatUnavailableError: No codec is registered, or the codec does not
141
+ support compression (decode-only).
142
+ """
143
+ if fmt is Format.NONE:
144
+ msg = "Format.NONE is not a compression format"
145
+ raise CompressionError(msg)
146
+ if fmt is Format.SCRUB:
147
+ msg = "Format.SCRUB is not a compression format — use ntcompress.ese.scrub"
148
+ raise CompressionError(msg)
149
+ if fmt is Format.MAXIMUM:
150
+ msg = "Format.MAXIMUM is a sentinel value, not a compression format"
151
+ raise CompressionError(msg)
152
+ module = _get(fmt)
153
+ if not hasattr(module, "compress"):
154
+ msg = f"format {fmt.name} (0x{fmt.value:x}) is decode-only; no encoder is available"
155
+ raise FormatUnavailableError(msg)
156
+ return module.compress(data)
157
+
158
+
159
+ def decompress(blob: Buffer, fmt: Format | None = None) -> bytes:
160
+ """Decode a framed ESE cell.
161
+
162
+ When ``fmt`` is None, the format is auto-detected from the header byte.
163
+
164
+ Args:
165
+ blob: The framed cell, including the header byte.
166
+ fmt: The format to use, or None for auto-detection.
167
+
168
+ Raises:
169
+ DecompressionError: Empty buffer, unknown format id, or decode failure.
170
+ ScrubDetectedError: The record is a SCRUB (0x4) erase marker.
171
+ FormatUnavailableError: The format is known but no codec is registered.
172
+ """
173
+ if fmt is None:
174
+ fmt = _format_of(blob)
175
+ if fmt is Format.NONE:
176
+ msg = "Format.NONE has no compression header; pass the raw cell body instead"
177
+ raise DecompressionError(msg)
178
+ if fmt is Format.SCRUB:
179
+ msg = "record is a SCRUB erase marker; no plaintext is recoverable — use ntcompress.ese.scrub"
180
+ raise ScrubDetectedError(msg)
181
+ if fmt is Format.MAXIMUM:
182
+ msg = "Format.MAXIMUM is a sentinel value, not a compression format"
183
+ raise DecompressionError(msg)
184
+ return _get(fmt).decompress(blob)
185
+
186
+
187
+ def decompressed_size(blob: Buffer) -> int:
188
+ """Return a framed cell's recorded plaintext length without decoding.
189
+
190
+ Auto-detects the format from the header byte.
191
+
192
+ Raises:
193
+ DecompressionError: Empty buffer or unknown format id.
194
+ ScrubDetectedError: The record is a SCRUB erase marker.
195
+ FormatUnavailableError: The format is known but no codec is registered.
196
+ """
197
+ fmt = _format_of(blob)
198
+ if fmt is Format.NONE:
199
+ msg = "Format.NONE has no compression header; the size is the raw body length"
200
+ raise DecompressionError(msg)
201
+ if fmt is Format.SCRUB:
202
+ msg = "record is a SCRUB erase marker; it has no decompressed size — use ntcompress.ese.scrub"
203
+ raise ScrubDetectedError(msg)
204
+ return _get(fmt).decompressed_size(blob)
205
+
206
+
207
+ # --- Auto-registration of codec modules ---
208
+
209
+ from ntcompress.ese import lz4, sevenbit_ascii, sevenbit_unicode, xpress, xpress9, xpress10 # noqa: E402
210
+
211
+ _register(Format.SEVEN_BIT_ASCII, sevenbit_ascii)
212
+ _register(Format.SEVEN_BIT_UNICODE, sevenbit_unicode)
213
+ _register(Format.XPRESS, xpress)
214
+ _register(Format.XPRESS9, xpress9)
215
+ _register(Format.XPRESS10, xpress10)
216
+ _register(Format.LZ4, lz4)
@@ -0,0 +1,32 @@
1
+ """Internal dispatch table for ESE compression formats.
2
+
3
+ Maps :class:`Format` enum members to the modules that implement them. Each codec
4
+ module is imported and registered when :mod:`ntcompress.ese` is first loaded.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ from ntcompress.exceptions import FormatUnavailableError
12
+
13
+ if TYPE_CHECKING:
14
+ from types import ModuleType
15
+
16
+ from ntcompress.ese import Format
17
+
18
+ _CODECS: dict[Format, ModuleType] = {}
19
+
20
+
21
+ def _register(fmt: Format, module: ModuleType) -> None:
22
+ """Register a codec module for a given format."""
23
+ _CODECS[fmt] = module
24
+
25
+
26
+ def _get(fmt: Format) -> ModuleType:
27
+ """Look up the codec module for a format, or raise."""
28
+ module = _CODECS.get(fmt)
29
+ if module is None:
30
+ msg = f"no codec registered for ESE format {fmt.name} (0x{fmt.value:x})"
31
+ raise FormatUnavailableError(msg)
32
+ return module
@@ -0,0 +1,167 @@
1
+ """Internal shared helpers for 7-bit ASCII and Unicode codecs.
2
+
3
+ These two schemes share their framing and packer, so the common infrastructure lives
4
+ here. Each packs 7 significant bits per source unit LSB-first into a continuous
5
+ bitstream: 7BITASCII over bytes, 7BITUNICODE over UTF-16LE code units whose high byte
6
+ is zero (so the wide scheme differs only in its 2-byte source stride and in re-emitting
7
+ the ``0x00`` high byte on decode). The low 3 bits of the header byte hold the number of
8
+ valid bits in the final packed byte, stored biased as 0-7 meaning 1-8.
9
+
10
+ There is no public specification -- [MS-XCA] scopes only the Xpress family -- so the
11
+ authority is the MIT-licensed ESE source: ``compression.cxx:985-1004`` (size math),
12
+ ``:1168-1387`` / ``:1390-1504`` (ASCII/Unicode writers), ``:2113-2185`` /
13
+ ``:2188-2272`` (ASCII/Unicode readers).
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from dataclasses import dataclass
19
+ from typing import TYPE_CHECKING, Final
20
+
21
+ from ntcompress.exceptions import DecompressionError
22
+
23
+ if TYPE_CHECKING:
24
+ from ntcompress.ese import Format
25
+
26
+ # --- Constants ---
27
+
28
+ UNIT_BITS: Final = 7
29
+ """Packed bits per source unit; the writers' fixed ``cbits = 7`` (compression.cxx:1310)."""
30
+
31
+ UNIT_MASK: Final = 0x7F
32
+ """Mask of one packed unit; both readers extract ``(x >> ibit) & 0x7F`` (compression.cxx:2166, 2243)."""
33
+
34
+ _BYTE_BITS: Final = 8
35
+ _WIDE_STRIDE: Final = 2 # bytes per UTF-16LE code unit (sizeof(WORD), compression.cxx:1002)
36
+
37
+ MIN_CELL_SIZE: Final = 2
38
+ """Smallest well-formed cell: header byte + one packed byte, which the readers' ``Cb - 2`` size math presumes (compression.cxx:2135)."""
39
+
40
+
41
+ # --- Shared framing ---
42
+
43
+
44
+ @dataclass(frozen=True)
45
+ class SevenBitHeader:
46
+ """A parsed 7-bit cell header, per ``ErrDecompress7Bit*_`` (compression.cxx:2127-2137).
47
+
48
+ Captures the two facts the readers derive before unpacking: how many bits of
49
+ the last packed byte are valid, and hence exactly how many 7-bit units the
50
+ stream holds.
51
+ """
52
+
53
+ fmt: Format
54
+ """The format id from the header's top 5 bits (SEVEN_BIT_ASCII or SEVEN_BIT_UNICODE)."""
55
+
56
+ final_byte_bits: int
57
+ """Valid bits in the last packed byte, 1-8: ``(bHeader & 0x7) + 1`` (compression.cxx:2131)."""
58
+
59
+ unit_count: int
60
+ """Number of 7-bit units in the stream: ``((Cb - 2) * 8 + final_byte_bits) // 7`` (compression.cxx:2135-2137)."""
61
+
62
+
63
+ def _parse_header(blob: bytes, expected: Format) -> SevenBitHeader:
64
+ """Validate a framed 7-bit cell and derive its unit count.
65
+
66
+ Ports the size prologue shared by both readers (compression.cxx:2127-2137).
67
+ ESE only *asserts* ``cbitTotal % 7 == 0`` in DEBUG builds and floor-divides in
68
+ retail; real-world producers do emit non-canonical bit counts (the same
69
+ Exchange payload circulates with header ``0x10`` and ``0x0e``), so this port
70
+ keeps the retail floor-division behavior.
71
+
72
+ Args:
73
+ blob: The framed cell, header byte included.
74
+ expected: The format the calling codec owns.
75
+
76
+ Returns:
77
+ The parsed header.
78
+
79
+ Raises:
80
+ DecompressionError: The cell is shorter than header + one stream byte, or
81
+ its format id is not ``expected``.
82
+ """
83
+ from ntcompress.ese import format_flags, format_id
84
+
85
+ if len(blob) < MIN_CELL_SIZE:
86
+ msg = f"a 7-bit cell needs a header byte plus at least one packed byte, got {len(blob)} byte(s)"
87
+ raise DecompressionError(msg)
88
+ raw = format_id(blob[0])
89
+ if raw != expected:
90
+ msg = f"cell header carries format id 0x{raw:x}, not {expected.name} (0x{expected.value:x})"
91
+ raise DecompressionError(msg)
92
+ final_byte_bits = format_flags(blob[0]) + 1
93
+ total_bits = (len(blob) - 2) * _BYTE_BITS + final_byte_bits
94
+ return SevenBitHeader(fmt=expected, final_byte_bits=final_byte_bits, unit_count=total_bits // UNIT_BITS)
95
+
96
+
97
+ def _check_padding(blob: bytes, header: SevenBitHeader) -> None:
98
+ """Reject a cell whose declared-invalid final-byte bits are non-zero.
99
+
100
+ ESE's writers flush from a zero-initialized accumulator, so the padding bits
101
+ above ``final_byte_bits`` are always zero in a well-formed cell. This checks only
102
+ those high bits of the final packed byte; libesedb performs a comparable (not
103
+ identical) padding-rejection check on corrupt streams (cf. ``value_16bit != 0``,
104
+ libesedb_compression.c:220). Gated on ``verify`` by the callers.
105
+ """
106
+ if blob[-1] >> header.final_byte_bits:
107
+ msg = f"non-zero padding above the {header.final_byte_bits} declared valid bit(s) of the final packed byte"
108
+ raise DecompressionError(msg)
109
+
110
+
111
+ def _unpack_units(stream: bytes, count: int) -> bytearray:
112
+ """Unpack ``count`` LSB-first 7-bit units from a packed stream.
113
+
114
+ Accumulator port of the readers' inner loop (compression.cxx:2154-2180): the C
115
+ code re-reads a byte or little-endian WORD at each bit offset, which is exactly
116
+ equivalent to draining 7-bit units off a little-endian accumulator. ``count``
117
+ comes from :func:`_parse_header`, which guarantees the stream holds enough bits.
118
+ """
119
+ out = bytearray()
120
+ accumulator = 0
121
+ bits = 0
122
+ for byte in stream:
123
+ accumulator |= byte << bits
124
+ bits += _BYTE_BITS
125
+ while bits >= UNIT_BITS:
126
+ if len(out) == count:
127
+ return out
128
+ out.append(accumulator & UNIT_MASK)
129
+ accumulator >>= UNIT_BITS
130
+ bits -= UNIT_BITS
131
+ return out
132
+
133
+
134
+ def _pack_units(units: bytes) -> bytearray:
135
+ """Pack 7-bit values LSB-first into a byte stream.
136
+
137
+ Accumulator port of the writers' slow path (compression.cxx:1298-1348 ASCII,
138
+ :1413-1464 Unicode): OR each unit's 7 bits at the current bit offset and flush
139
+ whole bytes. The final partial byte is always written, zero-padded high --
140
+ matching ESE's ``(ibitOutputCurr + 7) / 8`` trailing flush (:1354-1362).
141
+ """
142
+ out = bytearray()
143
+ accumulator = 0
144
+ bits = 0
145
+ for value in units:
146
+ accumulator |= value << bits
147
+ bits += UNIT_BITS
148
+ if bits >= _BYTE_BITS:
149
+ out.append(accumulator & 0xFF)
150
+ accumulator >>= _BYTE_BITS
151
+ bits -= _BYTE_BITS
152
+ if bits:
153
+ out.append(accumulator)
154
+ return out
155
+
156
+
157
+ def _frame(fmt: Format, units: bytes) -> bytes:
158
+ """Build a framed cell: header byte + packed stream.
159
+
160
+ The stored bit count is ``(ibitOutputCurr - 1) % 8`` (compression.cxx:1379,
161
+ :1497), which for ``n`` units reduces to ``(7n - 1) % 8`` -- the writers' 0->32
162
+ fixup for an exactly-full final DWORD (:1374-1378) folds into the same formula.
163
+ """
164
+ from ntcompress.ese import header_byte
165
+
166
+ final_bits_biased = (len(units) * UNIT_BITS - 1) % _BYTE_BITS
167
+ return bytes([header_byte(fmt, final_bits_biased)]) + bytes(_pack_units(units))
@@ -0,0 +1,97 @@
1
+ """Checksums used by ESE compression headers.
2
+
3
+ Two non-stdlib CRCs are required, and both are implemented here from their literal
4
+ parameters. Python's :func:`zlib.crc32` uses a different polynomial and must not be
5
+ substituted for either.
6
+
7
+ * :func:`crc32c_ese` -- CRC-32C / Castagnoli (reflected polynomial ``0x82F63B78``,
8
+ normal form ``0x1EDC6F41``; init/xorout ``0xFFFFFFFF``): the "SSE 4.2 compatible" CRC
9
+ computed over the XPRESS10 plaintext. Verified check value
10
+ ``crc32c_ese(b"123456789") == 0xE3069283``.
11
+ * :func:`crc64_ese` -- reflected polynomial ``0x9A6C9329AC4BC9B5``, init/xorout
12
+ all-ones: the "Corsica compatible" CRC computed over the XPRESS10 compressed
13
+ payload. Verified check value ``crc64_ese(b"123456789") == 0xAE8B14860A799888``.
14
+ This parameterization is **CRC-64/NVME** (RevEng catalogue: normal polynomial
15
+ ``0xAD93D23594C93659``, reflected ``0x9A6C9329AC4BC9B5``, init/xorout all-ones,
16
+ refin/refout, check ``0xAE8B14860A799888``). It is NOT CRC-64/XZ (reflected poly
17
+ ``0xC96C5795D7870F42``); do not use a library preset named ``crc64('xz')``.
18
+
19
+ Both are little-endian / reflected CRCs, so a right-shifting byte-wise table drives
20
+ them. The polynomials are already given in reflected form.
21
+
22
+ Authority: ``dev/ese/src/_xpress10/xpress10sw.cxx:34-59`` (the CRC-64 bit loop, poly
23
+ ``CORSICA_CRC64_POLY``) and ESE ``Crc32Checksum`` in ``dev/ese/src/os/encrypt.cxx``
24
+ (CRC-32C).
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ from typing import TYPE_CHECKING, Final
30
+
31
+ if TYPE_CHECKING:
32
+ from ntcompress._types import Buffer
33
+
34
+ # --- Polynomials (reflected / LSB-first form) ---
35
+
36
+ CRC32C_POLY: Final = 0x82F63B78
37
+ """Reflected CRC-32C (Castagnoli) polynomial (normal form 0x1EDC6F41)."""
38
+
39
+ CRC64_ESE_POLY: Final = 0x9A6C9329AC4BC9B5
40
+ """Reflected CRC-64/NVME polynomial (xpress10sw.cxx:35, ``CORSICA_CRC64_POLY``). Not CRC-64/XZ."""
41
+
42
+ _MASK32: Final = 0xFFFFFFFF
43
+ _MASK64: Final = 0xFFFFFFFFFFFFFFFF
44
+
45
+
46
+ def _make_table(poly: int, mask: int) -> tuple[int, ...]:
47
+ """Build a 256-entry byte-wise lookup table for a reflected (right-shifting) CRC."""
48
+ table: list[int] = []
49
+ for index in range(256):
50
+ crc = index
51
+ for _ in range(8):
52
+ crc = (crc >> 1) ^ poly if crc & 1 else crc >> 1
53
+ crc &= mask
54
+ table.append(crc)
55
+ return tuple(table)
56
+
57
+
58
+ _CRC32C_TABLE: Final = _make_table(CRC32C_POLY, _MASK32)
59
+ _CRC64_TABLE: Final = _make_table(CRC64_ESE_POLY, _MASK64)
60
+
61
+
62
+ def crc32c_ese(data: Buffer) -> int:
63
+ """Return the CRC-32C (Castagnoli) of ``data``, as ESE stores it in headers.
64
+
65
+ Reflected, init/xorout ``0xFFFFFFFF``. This is the "SSE 4.2 compatible" checksum
66
+ ESE computes over uncompressed data (``Crc32Checksum``); the XPRESS10 header
67
+ stores it over the plaintext.
68
+
69
+ Args:
70
+ data: The bytes to checksum.
71
+
72
+ Returns:
73
+ The 32-bit CRC-32C. ``crc32c_ese(b"123456789") == 0xE3069283``.
74
+ """
75
+ crc = _MASK32
76
+ for byte in data:
77
+ crc = (crc >> 8) ^ _CRC32C_TABLE[(crc ^ byte) & 0xFF]
78
+ return crc ^ _MASK32
79
+
80
+
81
+ def crc64_ese(data: Buffer) -> int:
82
+ """Return the ESE/Corsica CRC-64 of ``data``.
83
+
84
+ Reflected poly ``0x9A6C9329AC4BC9B5``, init/xorout all-ones -- the CRC-64/NVME
85
+ parameterization. The XPRESS10 header stores this over the compressed payload
86
+ (``UtilGenCorsicaCrc64``, ``xpress10sw.cxx:34-59``).
87
+
88
+ Args:
89
+ data: The bytes to checksum.
90
+
91
+ Returns:
92
+ The 64-bit CRC. ``crc64_ese(b"123456789") == 0xAE8B14860A799888``.
93
+ """
94
+ crc = _MASK64
95
+ for byte in data:
96
+ crc = (crc >> 8) ^ _CRC64_TABLE[(crc ^ byte) & 0xFF]
97
+ return crc ^ _MASK64