Verified CRC source-code for C, C#, Go, Python, Rust, TypeScript, Verilog, and VHDL — catalogue-driven, typed introspection API, self-test embedded.
Project description
crcglot
Verified CRC source code for C / C++ ⚙️, Rust 🦀, Go 🚦, C# 💠, Python 🐍, TypeScript 🔷, Verilog 🔧, and VHDL 🔌. Catalogue-driven, self-test embedded, multi-language by design. Pure-stdlib package — zero runtime dependencies.
LLMs will gladly write you CRC code. It might even be right. crcglot guarantees the generated code matches the canonical reveng catalogue test vector (crc("123456789") == <check value>) and ships a self-test you can run on your toolchain to prove it.
Quick start
uv tool install crcglot # or: pip install crcglot
crcglot c crc32 file=mycrc
That's it. You now have mycrc.h and mycrc.c — drop-in CRC-32 with a built-in _self_test() you can call to verify it matches the canonical reveng check value.
Different language? Swap c for python / rust / vhdl / verilog / go / csharp / typescript. Different algorithm? Run crcglot list to browse all 71.
Installation
| Tool | Command | Use when |
|---|---|---|
| uv (recommended) | uv tool install crcglot |
You just want the crcglot CLI on PATH. Isolated install, no global pollution. |
| uv (as a library) | uv add crcglot |
You're calling the generators from Python (e.g. a build script that emits CRC code into your repo). |
| pip | pip install crcglot |
You don't have uv. Identical package, slower install. |
| pipx | pipx install crcglot |
Same isolation story as uv tool, if pipx is what you have. |
Python 3.11+, no other runtime dependencies — crcglot itself is pure stdlib. Per-target toolchains (gcc, rustc, tsx, iverilog, etc.) only matter if you want to run the generated code; the generator produces source either way.
Or use it from Python code:
from crcglot import LANGUAGES
header, source = LANGUAGES["c"].generator("crc32")
Both surfaces are documented in detail below.
What you get per language
| Function | Purpose |
|---|---|
<fname>_init / _update / _finalize |
Streaming triple — feed data chunk by chunk |
<fname> |
One-shot wrapper that calls the streaming triple |
<fname>_self_test |
Verify against the reveng check value on your toolchain |
Every target ships a runtime-callable _self_test(): C returns 0/1; Rust / Go / C# / TypeScript / Python / Verilog / VHDL return bool / boolean / bit. No #[cfg(test)] gating — call it from your release build, a boot self-check, or a startup assertion.
How it's verified
CI runs the Python-level suite on every push: every algorithm in the reveng catalogue is checked against its hardcoded canonical check value — not the catalogue's own check field, so a silent regression in the engine can't hide — and the Python generator is run end-to-end (generated, exec'd, and called on b"123456789") against the same hardcoded vectors. The slow tier on top of that compiles and executes the generated source for every algorithm in C, Rust, Go, C#, TypeScript, Verilog, and VHDL via gcc / rustc / go / dotnet / tsx (Node) / iverilog / ghdl and re-checks the runtime result — same algorithm coverage, exercised through each real toolchain.
Every generated file also ships its own _self_test() carrying that same canonical vector. For every target except Python, you should call _self_test() once in your build environment — wire it into a unit test, a startup assertion, or your boot self-check. Our CI proves the generator emits correct code on our reference toolchain; only running _self_test() on yours proves your compiler version, optimization flags, target endianness, and integer widths haven't introduced a subtle disagreement. Python is the exception: the interpreter that ran the CI suite is the one running your code, so the in-environment check would be redundant.
CLI reference
crcglot <command> [options...]
crcglot list [GLOB]
Browse the catalogue. Optional GLOB filters by shell-style pattern (e.g. crc16-*). Exit code 1 if nothing matches.
crcglot list # all 71 algorithms
crcglot list 'crc32-*' # just the CRC-32 family
crcglot info <name>
Print parameters (width, poly, init, refin, refout, xorout, check, desc) for one algorithm. Exit 1 on unknown name.
crcglot info crc64-xz
crcglot {c | csharp | go | python | rust | typescript | verilog | vhdl} <algorithm> [options...] [tokens...]
Generate source code for the chosen target language.
| Option / token | Effect |
|---|---|
| (default) bit-by-bit | Smallest code, zero RAM table, slowest. All widths. |
--table |
256-entry lookup table, 4-8× faster. All widths. |
--slice8 |
8 lookup tables, 5-10× faster than --table. CRC-32 / CRC-64 only. Compiled-software targets. |
--custom |
Use raw Rocksoft/Williams params instead of a catalogue lookup (see below). |
file=STEM |
Write to disk (extension picked per language; see below). Omit for stdout. |
symbol=NAME |
Override the emitted function name. Default: derived from algorithm, or from file=STEM if given. |
File extensions per language: C emits STEM.h + STEM.c; Python .py; Rust .rs; VHDL .vhd; Verilog .sv (SystemVerilog 2012); Go .go; C# .cs; TypeScript .ts.
Rules:
--tableand--slice8are mutually exclusive (exit 2 if both given).--slice8 pythonsilently falls back to--table(CPython's per-int overhead eats the slice-by-8 speedup; stderr warns).- Without
file=, output goes to stdout. For C, header is emitted first, then source. - C / Rust / VHDL files embed
<symbol>_self_test()returning 0 on success. In constrained embedded targets, standard toolchain flags (-Wl,--gc-sectionsfor C, LTO for Rust) strip whatever you don't call.
--custom (raw Rocksoft/Williams parameters)
For algorithms not in the catalogue:
crcglot c --custom width=16 poly=0x1234 init=0xFFFF \
refin=true refout=true xorout=0x0000 file=mycustom
| Param | Required | Notes |
|---|---|---|
width=N |
yes | 8, 16, 32, or 64 only |
poly=X |
yes | Hex (0x...) or decimal |
init=X |
no | Default 0. Hex or decimal. |
refin=B |
no | Default false. Accepts true/false/1/0/yes/no/on/off. |
refout=B |
no | Default false. Same boolean syntax. |
xorout=X |
no | Default 0. |
name=NAME |
no | Default crc_custom. Used in generated comments. |
desc=TEXT |
no | Free-form description in comments. |
The check value for the custom parameters is computed automatically (generic_crc(b"123456789", ...)) and embedded into the generated _self_test().
Catalogue
64+ algorithms covering everything from CRC-8 (ATM, AUTOSAR, Bluetooth, Maxim 1-Wire) through CRC-16 (Modbus, XMODEM, CCITT, IBM SDLC) through CRC-32 (Ethernet, bzip2, iSCSI, AUTOSAR) to CRC-64 (XZ, ECMA-182, NVMe, Redis). Browse with crcglot list.
Programmatic API
Two registries, both keyed by short code:
LANGUAGES — supported target languages
from crcglot import LANGUAGES
for code, info in LANGUAGES.items():
print(f"{info.emoji} {info.display_name:<10} {info.extensions} "
f"{sorted(info.variants)}")
# → ⚙️ C / C++ ('.h', '.c') ['bitwise', 'slice8', 'table']
# → 💠 C# ('.cs',) ['bitwise', 'slice8', 'table']
# → 🚦 Go ('.go',) ['bitwise', 'slice8', 'table']
# → 🐍 Python ('.py',) ['bitwise', 'table']
# → 🦀 Rust ('.rs',) ['bitwise', 'slice8', 'table']
# → 🔷 TypeScript ('.ts',) ['bitwise', 'slice8', 'table']
# → 🔧 Verilog ('.sv',) ['bitwise']
# → 🔌 VHDL ('.vhd',) ['bitwise']
Each entry is a frozen LanguageInfo dataclass with:
code— dispatch key ("c","csharp", ...,"typescript","verilog")extensions— file extension tuple ((".h", ".c")for C; single-element for the rest)variants— subset of{"bitwise", "table", "slice8"}that the generator acceptsgenerator(name, ...)— name-lookup callable (returns source string, or(header, source)tuple for C)generator_from_entry(name, algo, ...)— bypass the catalogue with a customAlgorithmInfoemoji— single-grapheme pictographic identifier for terminals / docsdisplay_name— human-readable name (e.g."C / C++","TypeScript") — distinct fromcode
ALGORITHMS — the reveng CRC catalogue
from crcglot import ALGORITHMS
modbus = ALGORITHMS["crc16-modbus"]
print(modbus.width, hex(modbus.check), modbus.desc)
# → 16 0x4b37 Modbus RTU serial protocol
# Filter to CRC-32 only.
crc32_family = [a for a in ALGORITHMS.values() if a.width == 32]
Each entry is a frozen AlgorithmInfo dataclass with the full Rocksoft / Williams parameter set: name, width, poly, init, refin, refout, xorout, check, desc.
Custom polynomials
from crcglot import AlgorithmInfo, LANGUAGES, generic_crc
# Compute the canonical check value for a custom poly.
check = generic_crc(b"123456789", 16, 0x1234, 0xFFFF, True, True, 0x0000)
# Build an AlgorithmInfo and feed it to any generator.
algo = AlgorithmInfo(
name="my_crc16", width=16, poly=0x1234, init=0xFFFF,
refin=True, refout=True, xorout=0x0000, check=check,
desc="My custom CRC-16",
)
code = LANGUAGES["rust"].generator_from_entry("my_crc16", algo, table=True)
Example output
See EXAMPLES.md for the actual generated source for crc32 across every language × implementation combination (C / Rust / Python / VHDL / Verilog / Go / C# / TypeScript crossed with bit-by-bit, table-driven, and slice-by-8 where supported). Every block is reproducible with one CLI command.
Acknowledgments
CRC catalogue data is derived from Greg Cook's reveng project — the canonical source for CRC algorithm parameters since 1999.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file crcglot-0.7.0.tar.gz.
File metadata
- Download URL: crcglot-0.7.0.tar.gz
- Upload date:
- Size: 41.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
218d3f5e15b6cd16bdf951899923b8e9d93ea2d2adecdc91c205629a6766ab31
|
|
| MD5 |
d6f389df972d8473b124b6bb08188775
|
|
| BLAKE2b-256 |
0095e6d805e85dd22047d88f7dc340e958abe0b06670e5e2ea874de133660cf3
|
Provenance
The following attestation bundles were made for crcglot-0.7.0.tar.gz:
Publisher:
publish.yml on hucker/crcglot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
crcglot-0.7.0.tar.gz -
Subject digest:
218d3f5e15b6cd16bdf951899923b8e9d93ea2d2adecdc91c205629a6766ab31 - Sigstore transparency entry: 1635502558
- Sigstore integration time:
-
Permalink:
hucker/crcglot@d54a881946771342f68d379c773e064c62d23592 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/hucker
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d54a881946771342f68d379c773e064c62d23592 -
Trigger Event:
push
-
Statement type:
File details
Details for the file crcglot-0.7.0-py3-none-any.whl.
File metadata
- Download URL: crcglot-0.7.0-py3-none-any.whl
- Upload date:
- Size: 55.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc68dfd0d479dc4a889666da7aa9cdf9455600fe5d642fd0fd88f6cec3a3d11a
|
|
| MD5 |
ca9b5c0ad8e8a2cd3bc3473f48183816
|
|
| BLAKE2b-256 |
7acccce05c31199f8e25d279208f7b947edb6ddb0e7e13d43ab80b0dc4fc7468
|
Provenance
The following attestation bundles were made for crcglot-0.7.0-py3-none-any.whl:
Publisher:
publish.yml on hucker/crcglot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
crcglot-0.7.0-py3-none-any.whl -
Subject digest:
bc68dfd0d479dc4a889666da7aa9cdf9455600fe5d642fd0fd88f6cec3a3d11a - Sigstore transparency entry: 1635502566
- Sigstore integration time:
-
Permalink:
hucker/crcglot@d54a881946771342f68d379c773e064c62d23592 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/hucker
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d54a881946771342f68d379c773e064c62d23592 -
Trigger Event:
push
-
Statement type: