Python CRC Code Example (Online Runner)

Python CRC-8/16/32/64 examples with preset variants, hex/decimal output, and file checksums matching the CRC tools.

Online calculator: use the site CRC text tool.

Calculation method

The CRC tools expose many preset variants (polynomial, init, xor-out, and reflection flags) plus output format (hex or decimal). The helpers below mirror those presets and let you compute all variants or a single chosen ID.

Implementation notes

  • Package: no external dependency; CRCs are implemented directly in Python.
  • Implementation: each preset defines width, polynomial, init, xor-out, and reflect-in/out behavior. Output is normalized to uppercase hex or decimal to match the tool.
  • Notes: CRCs are error-detection codes, not cryptographic hashes. Any change in input bytes (including newline or encoding) changes the result.
python
from __future__ import annotations

from pathlib import Path
from typing import Literal

OutputFormat = Literal["hex", "decimal"]

CRC_VARIANTS = [
    # CRC-8
    {"id": "crc8-autosar", "label": "CRC-8/AUTOSAR", "width": 8, "poly": 0x2F, "init": 0xFF, "xor": 0xFF, "ref_in": False, "ref_out": False},
    {"id": "crc8-bluetooth", "label": "CRC-8/BLUETOOTH", "width": 8, "poly": 0xA7, "init": 0x00, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-cdma2000", "label": "CRC-8/CDMA2000", "width": 8, "poly": 0x9B, "init": 0xFF, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-darc", "label": "CRC-8/DARC", "width": 8, "poly": 0x39, "init": 0x00, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-dvb-s2", "label": "CRC-8/DVB-S2", "width": 8, "poly": 0xD5, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-gsm-a", "label": "CRC-8/GSM-A", "width": 8, "poly": 0x1D, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-gsm-b", "label": "CRC-8/GSM-B", "width": 8, "poly": 0x49, "init": 0x00, "xor": 0xFF, "ref_in": False, "ref_out": False},
    {"id": "crc8-hitag", "label": "CRC-8/HITAG", "width": 8, "poly": 0x1D, "init": 0xFF, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-i-432-1", "label": "CRC-8/I-432-1", "width": 8, "poly": 0x07, "init": 0x00, "xor": 0x55, "ref_in": False, "ref_out": False},
    {"id": "crc8-i-code", "label": "CRC-8/I-CODE", "width": 8, "poly": 0x1D, "init": 0xFD, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-lte", "label": "CRC-8/LTE", "width": 8, "poly": 0x9B, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-maxim-dow", "label": "CRC-8/MAXIM-DOW", "width": 8, "poly": 0x31, "init": 0x00, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-mifare-mad", "label": "CRC-8/MIFARE-MAD", "width": 8, "poly": 0x1D, "init": 0xC7, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-nrsc-5", "label": "CRC-8/NRSC-5", "width": 8, "poly": 0x31, "init": 0xFF, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-opensafety", "label": "CRC-8/OPENSAFETY", "width": 8, "poly": 0x2F, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-rohc", "label": "CRC-8/ROHC", "width": 8, "poly": 0x07, "init": 0xFF, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-sae-j1850", "label": "CRC-8/SAE-J1850", "width": 8, "poly": 0x1D, "init": 0xFF, "xor": 0xFF, "ref_in": False, "ref_out": False},
    {"id": "crc8-smbus", "label": "CRC-8/SMBUS", "width": 8, "poly": 0x07, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-tech-3250", "label": "CRC-8/TECH-3250", "width": 8, "poly": 0x1D, "init": 0xFF, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-wcdma", "label": "CRC-8/WCDMA", "width": 8, "poly": 0x9B, "init": 0x00, "xor": 0x00, "ref_in": True, "ref_out": True},
    # CRC-16
    {"id": "crc16-arc", "label": "CRC-16/ARC", "width": 16, "poly": 0x8005, "init": 0x0000, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-cdma2000", "label": "CRC-16/CDMA2000", "width": 16, "poly": 0xC867, "init": 0xFFFF, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-cms", "label": "CRC-16/CMS", "width": 16, "poly": 0x8005, "init": 0xFFFF, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-dds-110", "label": "CRC-16/DDS-110", "width": 16, "poly": 0x8005, "init": 0x800D, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-dect-r", "label": "CRC-16/DECT-R", "width": 16, "poly": 0x0589, "init": 0x0000, "xor": 0x0001, "ref_in": False, "ref_out": False},
    {"id": "crc16-dect-x", "label": "CRC-16/DECT-X", "width": 16, "poly": 0x0589, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-dnp", "label": "CRC-16/DNP", "width": 16, "poly": 0x3D65, "init": 0x0000, "xor": 0xFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc16-en-13757", "label": "CRC-16/EN-13757", "width": 16, "poly": 0x3D65, "init": 0x0000, "xor": 0xFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc16-genibus", "label": "CRC-16/GENIBUS", "width": 16, "poly": 0x1021, "init": 0xFFFF, "xor": 0xFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc16-gsm", "label": "CRC-16/GSM", "width": 16, "poly": 0x1021, "init": 0x0000, "xor": 0xFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc16-ibm-3740", "label": "CRC-16/IBM-3740", "width": 16, "poly": 0x1021, "init": 0xFFFF, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-ibm-sdlc", "label": "CRC-16/IBM-SDLC", "width": 16, "poly": 0x1021, "init": 0xFFFF, "xor": 0xFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc16-iso-iec-14443-3-a", "label": "CRC-16/ISO-IEC-14443-3-A", "width": 16, "poly": 0x1021, "init": 0xC6C6, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-kermit", "label": "CRC-16/KERMIT", "width": 16, "poly": 0x1021, "init": 0x0000, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-lj1200", "label": "CRC-16/LJ1200", "width": 16, "poly": 0x6F63, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-m17", "label": "CRC-16/M17", "width": 16, "poly": 0x5935, "init": 0xFFFF, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-maxim-dow", "label": "CRC-16/MAXIM-DOW", "width": 16, "poly": 0x8005, "init": 0x0000, "xor": 0xFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc16-mcrf4xx", "label": "CRC-16/MCRF4XX", "width": 16, "poly": 0x1021, "init": 0xFFFF, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-modbus", "label": "CRC-16/MODBUS", "width": 16, "poly": 0x8005, "init": 0xFFFF, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-nrsc-5", "label": "CRC-16/NRSC-5", "width": 16, "poly": 0x080B, "init": 0xFFFF, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-opensafety-a", "label": "CRC-16/OPENSAFETY-A", "width": 16, "poly": 0x5935, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-opensafety-b", "label": "CRC-16/OPENSAFETY-B", "width": 16, "poly": 0x755B, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-profibus", "label": "CRC-16/PROFIBUS", "width": 16, "poly": 0x1DCF, "init": 0xFFFF, "xor": 0xFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc16-riello", "label": "CRC-16/RIELLO", "width": 16, "poly": 0x1021, "init": 0xB2AA, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-spi-fujitsu", "label": "CRC-16/SPI-FUJITSU", "width": 16, "poly": 0x1021, "init": 0x1D0F, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-t10-dif", "label": "CRC-16/T10-DIF", "width": 16, "poly": 0x8BB7, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-teledisk", "label": "CRC-16/TELEDISK", "width": 16, "poly": 0xA097, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-tms37157", "label": "CRC-16/TMS37157", "width": 16, "poly": 0x1021, "init": 0x89EC, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-umts", "label": "CRC-16/UMTS", "width": 16, "poly": 0x8005, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-usb", "label": "CRC-16/USB", "width": 16, "poly": 0x8005, "init": 0xFFFF, "xor": 0xFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc16-xmodem", "label": "CRC-16/XMODEM", "width": 16, "poly": 0x1021, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    # CRC-32
    {"id": "crc32-aixm", "label": "CRC-32/AIXM", "width": 32, "poly": 0x814141AB, "init": 0x00000000, "xor": 0x00000000, "ref_in": False, "ref_out": False},
    {"id": "crc32-autosar", "label": "CRC-32/AUTOSAR", "width": 32, "poly": 0xF4ACFB13, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc32-base91-d", "label": "CRC-32/BASE91-D", "width": 32, "poly": 0xA833982B, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc32-bzip2", "label": "CRC-32/BZIP2", "width": 32, "poly": 0x04C11DB7, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc32-cd-rom-edc", "label": "CRC-32/CD-ROM-EDC", "width": 32, "poly": 0x8001801B, "init": 0x00000000, "xor": 0x00000000, "ref_in": True, "ref_out": True},
    {"id": "crc32-cksum", "label": "CRC-32/CKSUM", "width": 32, "poly": 0x04C11DB7, "init": 0x00000000, "xor": 0xFFFFFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc32-iscsi", "label": "CRC-32/ISCSI (Castagnoli)", "width": 32, "poly": 0x1EDC6F41, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc32-iso-hdlc", "label": "CRC-32/ISO-HDLC", "width": 32, "poly": 0x04C11DB7, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc32-jamcrc", "label": "CRC-32/JAMCRC", "width": 32, "poly": 0x04C11DB7, "init": 0xFFFFFFFF, "xor": 0x00000000, "ref_in": True, "ref_out": True},
    {"id": "crc32-mef", "label": "CRC-32/MEF", "width": 32, "poly": 0x741B8CD7, "init": 0xFFFFFFFF, "xor": 0x00000000, "ref_in": True, "ref_out": True},
    {"id": "crc32-mpeg-2", "label": "CRC-32/MPEG-2", "width": 32, "poly": 0x04C11DB7, "init": 0xFFFFFFFF, "xor": 0x00000000, "ref_in": False, "ref_out": False},
    {"id": "crc32-xfer", "label": "CRC-32/XFER", "width": 32, "poly": 0x000000AF, "init": 0x00000000, "xor": 0x00000000, "ref_in": False, "ref_out": False},
    # CRC-64
    {"id": "crc64-ecma", "label": "CRC-64/ECMA-182", "width": 64, "poly": 0x42F0E1EBA9EA3693, "init": 0x0000000000000000, "xor": 0x0000000000000000, "ref_in": False, "ref_out": False},
    {"id": "crc64-iso", "label": "CRC-64/ISO", "width": 64, "poly": 0x000000000000001B, "init": 0xFFFFFFFFFFFFFFFF, "xor": 0xFFFFFFFFFFFFFFFF, "ref_in": True, "ref_out": True},
]

CRC_PRESETS = {variant["id"]: variant for variant in CRC_VARIANTS}


def reflect_bits(value: int, width: int) -> int:
    result = 0
    for _ in range(width):
        result = (result << 1) | (value & 1)
        value >>= 1
    return result


def compute_crc(data: bytes, preset_id: str) -> str:
    preset = CRC_PRESETS[preset_id]
    width = preset["width"]
    mask = (1 << width) - 1
    crc = preset["init"] & mask
    top_bit = 1 << (width - 1)

    for byte in data:
        cur = reflect_bits(byte, 8) if preset["ref_in"] else byte
        crc ^= cur << (width - 8)
        for _ in range(8):
            if crc & top_bit:
                crc = (crc << 1) ^ preset["poly"]
            else:
                crc <<= 1
            crc &= mask

    if preset["ref_out"]:
        crc = reflect_bits(crc, width)

    crc ^= preset["xor"]
    crc &= mask
    hex_len = (width + 3) // 4
    return f"{crc:0{hex_len}x}"


def format_crc(value_hex: str, output_format: OutputFormat) -> str:
    if output_format == "hex":
        return value_hex.upper()
    return str(int(value_hex, 16))


def crc_all(text: str, output_format: OutputFormat = "hex") -> dict[str, str]:
    data = text.encode("utf-8")
    return {preset["id"]: format_crc(compute_crc(data, preset["id"]), output_format) for preset in CRC_VARIANTS}


def crc_file(path: Path, preset_id: str, output_format: OutputFormat = "hex") -> str:
    data = path.read_bytes()
    value_hex = compute_crc(data, preset_id)
    return format_crc(value_hex, output_format)

# Example usage
# Computes all variants for text and one preset for a temporary file.
import tempfile
from pathlib import Path

# Compute all CRC variants for a text payload, output in hex.
rows = crc_all("hello", output_format="hex")
print(rows["crc32-iso-hdlc"])

# Compute a single CRC preset and show decimal output.
with tempfile.TemporaryDirectory() as temp_dir:
    sample_path = Path(temp_dir) / "sample.bin"
    sample_path.write_bytes(b"hello")
    print(crc_file(sample_path, preset_id="crc32-iscsi", output_format="decimal"))

Complete script (implementation + tests)

python
from pathlib import Path
import tempfile
from typing import Literal

OutputFormat = Literal["hex", "decimal"]

CRC_VARIANTS = [
    # CRC-8
    {"id": "crc8-autosar", "label": "CRC-8/AUTOSAR", "width": 8, "poly": 0x2F, "init": 0xFF, "xor": 0xFF, "ref_in": False, "ref_out": False},
    {"id": "crc8-bluetooth", "label": "CRC-8/BLUETOOTH", "width": 8, "poly": 0xA7, "init": 0x00, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-cdma2000", "label": "CRC-8/CDMA2000", "width": 8, "poly": 0x9B, "init": 0xFF, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-darc", "label": "CRC-8/DARC", "width": 8, "poly": 0x39, "init": 0x00, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-dvb-s2", "label": "CRC-8/DVB-S2", "width": 8, "poly": 0xD5, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-gsm-a", "label": "CRC-8/GSM-A", "width": 8, "poly": 0x1D, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-gsm-b", "label": "CRC-8/GSM-B", "width": 8, "poly": 0x49, "init": 0x00, "xor": 0xFF, "ref_in": False, "ref_out": False},
    {"id": "crc8-hitag", "label": "CRC-8/HITAG", "width": 8, "poly": 0x1D, "init": 0xFF, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-i-432-1", "label": "CRC-8/I-432-1", "width": 8, "poly": 0x07, "init": 0x00, "xor": 0x55, "ref_in": False, "ref_out": False},
    {"id": "crc8-i-code", "label": "CRC-8/I-CODE", "width": 8, "poly": 0x1D, "init": 0xFD, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-lte", "label": "CRC-8/LTE", "width": 8, "poly": 0x9B, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-maxim-dow", "label": "CRC-8/MAXIM-DOW", "width": 8, "poly": 0x31, "init": 0x00, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-mifare-mad", "label": "CRC-8/MIFARE-MAD", "width": 8, "poly": 0x1D, "init": 0xC7, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-nrsc-5", "label": "CRC-8/NRSC-5", "width": 8, "poly": 0x31, "init": 0xFF, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-opensafety", "label": "CRC-8/OPENSAFETY", "width": 8, "poly": 0x2F, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-rohc", "label": "CRC-8/ROHC", "width": 8, "poly": 0x07, "init": 0xFF, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-sae-j1850", "label": "CRC-8/SAE-J1850", "width": 8, "poly": 0x1D, "init": 0xFF, "xor": 0xFF, "ref_in": False, "ref_out": False},
    {"id": "crc8-smbus", "label": "CRC-8/SMBUS", "width": 8, "poly": 0x07, "init": 0x00, "xor": 0x00, "ref_in": False, "ref_out": False},
    {"id": "crc8-tech-3250", "label": "CRC-8/TECH-3250", "width": 8, "poly": 0x1D, "init": 0xFF, "xor": 0x00, "ref_in": True, "ref_out": True},
    {"id": "crc8-wcdma", "label": "CRC-8/WCDMA", "width": 8, "poly": 0x9B, "init": 0x00, "xor": 0x00, "ref_in": True, "ref_out": True},
    # CRC-16
    {"id": "crc16-arc", "label": "CRC-16/ARC", "width": 16, "poly": 0x8005, "init": 0x0000, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-cdma2000", "label": "CRC-16/CDMA2000", "width": 16, "poly": 0xC867, "init": 0xFFFF, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-cms", "label": "CRC-16/CMS", "width": 16, "poly": 0x8005, "init": 0xFFFF, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-dds-110", "label": "CRC-16/DDS-110", "width": 16, "poly": 0x8005, "init": 0x800D, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-dect-r", "label": "CRC-16/DECT-R", "width": 16, "poly": 0x0589, "init": 0x0000, "xor": 0x0001, "ref_in": False, "ref_out": False},
    {"id": "crc16-dect-x", "label": "CRC-16/DECT-X", "width": 16, "poly": 0x0589, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-dnp", "label": "CRC-16/DNP", "width": 16, "poly": 0x3D65, "init": 0x0000, "xor": 0xFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc16-en-13757", "label": "CRC-16/EN-13757", "width": 16, "poly": 0x3D65, "init": 0x0000, "xor": 0xFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc16-genibus", "label": "CRC-16/GENIBUS", "width": 16, "poly": 0x1021, "init": 0xFFFF, "xor": 0xFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc16-gsm", "label": "CRC-16/GSM", "width": 16, "poly": 0x1021, "init": 0x0000, "xor": 0xFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc16-ibm-3740", "label": "CRC-16/IBM-3740", "width": 16, "poly": 0x1021, "init": 0xFFFF, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-ibm-sdlc", "label": "CRC-16/IBM-SDLC", "width": 16, "poly": 0x1021, "init": 0xFFFF, "xor": 0xFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc16-iso-iec-14443-3-a", "label": "CRC-16/ISO-IEC-14443-3-A", "width": 16, "poly": 0x1021, "init": 0xC6C6, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-kermit", "label": "CRC-16/KERMIT", "width": 16, "poly": 0x1021, "init": 0x0000, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-lj1200", "label": "CRC-16/LJ1200", "width": 16, "poly": 0x6F63, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-m17", "label": "CRC-16/M17", "width": 16, "poly": 0x5935, "init": 0xFFFF, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-maxim-dow", "label": "CRC-16/MAXIM-DOW", "width": 16, "poly": 0x8005, "init": 0x0000, "xor": 0xFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc16-mcrf4xx", "label": "CRC-16/MCRF4XX", "width": 16, "poly": 0x1021, "init": 0xFFFF, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-modbus", "label": "CRC-16/MODBUS", "width": 16, "poly": 0x8005, "init": 0xFFFF, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-nrsc-5", "label": "CRC-16/NRSC-5", "width": 16, "poly": 0x080B, "init": 0xFFFF, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-opensafety-a", "label": "CRC-16/OPENSAFETY-A", "width": 16, "poly": 0x5935, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-opensafety-b", "label": "CRC-16/OPENSAFETY-B", "width": 16, "poly": 0x755B, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-profibus", "label": "CRC-16/PROFIBUS", "width": 16, "poly": 0x1DCF, "init": 0xFFFF, "xor": 0xFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc16-riello", "label": "CRC-16/RIELLO", "width": 16, "poly": 0x1021, "init": 0xB2AA, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-spi-fujitsu", "label": "CRC-16/SPI-FUJITSU", "width": 16, "poly": 0x1021, "init": 0x1D0F, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-t10-dif", "label": "CRC-16/T10-DIF", "width": 16, "poly": 0x8BB7, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-teledisk", "label": "CRC-16/TELEDISK", "width": 16, "poly": 0xA097, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-tms37157", "label": "CRC-16/TMS37157", "width": 16, "poly": 0x1021, "init": 0x89EC, "xor": 0x0000, "ref_in": True, "ref_out": True},
    {"id": "crc16-umts", "label": "CRC-16/UMTS", "width": 16, "poly": 0x8005, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    {"id": "crc16-usb", "label": "CRC-16/USB", "width": 16, "poly": 0x8005, "init": 0xFFFF, "xor": 0xFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc16-xmodem", "label": "CRC-16/XMODEM", "width": 16, "poly": 0x1021, "init": 0x0000, "xor": 0x0000, "ref_in": False, "ref_out": False},
    # CRC-32
    {"id": "crc32-aixm", "label": "CRC-32/AIXM", "width": 32, "poly": 0x814141AB, "init": 0x00000000, "xor": 0x00000000, "ref_in": False, "ref_out": False},
    {"id": "crc32-autosar", "label": "CRC-32/AUTOSAR", "width": 32, "poly": 0xF4ACFB13, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc32-base91-d", "label": "CRC-32/BASE91-D", "width": 32, "poly": 0xA833982B, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc32-bzip2", "label": "CRC-32/BZIP2", "width": 32, "poly": 0x04C11DB7, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc32-cd-rom-edc", "label": "CRC-32/CD-ROM-EDC", "width": 32, "poly": 0x8001801B, "init": 0x00000000, "xor": 0x00000000, "ref_in": True, "ref_out": True},
    {"id": "crc32-cksum", "label": "CRC-32/CKSUM", "width": 32, "poly": 0x04C11DB7, "init": 0x00000000, "xor": 0xFFFFFFFF, "ref_in": False, "ref_out": False},
    {"id": "crc32-iscsi", "label": "CRC-32/ISCSI (Castagnoli)", "width": 32, "poly": 0x1EDC6F41, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc32-iso-hdlc", "label": "CRC-32/ISO-HDLC", "width": 32, "poly": 0x04C11DB7, "init": 0xFFFFFFFF, "xor": 0xFFFFFFFF, "ref_in": True, "ref_out": True},
    {"id": "crc32-jamcrc", "label": "CRC-32/JAMCRC", "width": 32, "poly": 0x04C11DB7, "init": 0xFFFFFFFF, "xor": 0x00000000, "ref_in": True, "ref_out": True},
    {"id": "crc32-mef", "label": "CRC-32/MEF", "width": 32, "poly": 0x741B8CD7, "init": 0xFFFFFFFF, "xor": 0x00000000, "ref_in": True, "ref_out": True},
    {"id": "crc32-mpeg-2", "label": "CRC-32/MPEG-2", "width": 32, "poly": 0x04C11DB7, "init": 0xFFFFFFFF, "xor": 0x00000000, "ref_in": False, "ref_out": False},
    {"id": "crc32-xfer", "label": "CRC-32/XFER", "width": 32, "poly": 0x000000AF, "init": 0x00000000, "xor": 0x00000000, "ref_in": False, "ref_out": False},
    # CRC-64
    {"id": "crc64-ecma", "label": "CRC-64/ECMA-182", "width": 64, "poly": 0x42F0E1EBA9EA3693, "init": 0x0000000000000000, "xor": 0x0000000000000000, "ref_in": False, "ref_out": False},
    {"id": "crc64-iso", "label": "CRC-64/ISO", "width": 64, "poly": 0x000000000000001B, "init": 0xFFFFFFFFFFFFFFFF, "xor": 0xFFFFFFFFFFFFFFFF, "ref_in": True, "ref_out": True},
]

CRC_PRESETS = {variant["id"]: variant for variant in CRC_VARIANTS}


def reflect_bits(value: int, width: int) -> int:
    result = 0
    for _ in range(width):
        result = (result << 1) | (value & 1)
        value >>= 1
    return result


def compute_crc(data: bytes, preset_id: str) -> str:
    preset = CRC_PRESETS[preset_id]
    width = preset["width"]
    mask = (1 << width) - 1
    crc = preset["init"] & mask
    top_bit = 1 << (width - 1)

    for byte in data:
        cur = reflect_bits(byte, 8) if preset["ref_in"] else byte
        crc ^= cur << (width - 8)
        for _ in range(8):
            if crc & top_bit:
                crc = (crc << 1) ^ preset["poly"]
            else:
                crc <<= 1
            crc &= mask

    if preset["ref_out"]:
        crc = reflect_bits(crc, width)

    crc ^= preset["xor"]
    crc &= mask
    hex_len = (width + 3) // 4
    return f"{crc:0{hex_len}x}"


def format_crc(value_hex: str, output_format: OutputFormat) -> str:
    if output_format == "hex":
        return value_hex.upper()
    return str(int(value_hex, 16))


def crc_all(text: str, output_format: OutputFormat = "hex") -> dict[str, str]:
    data = text.encode("utf-8")
    return {preset["id"]: format_crc(compute_crc(data, preset["id"]), output_format) for preset in CRC_VARIANTS}


def crc_file(path: Path, preset_id: str, output_format: OutputFormat = "hex") -> str:
    data = path.read_bytes()
    value_hex = compute_crc(data, preset_id)
    return format_crc(value_hex, output_format)

TEST_VECTOR = {
    "input": b"123456789",
    "crc32-iso-hdlc": "cbf43926",
    "crc16-arc": "bb3d",
}


def run_tests() -> None:
    data = TEST_VECTOR["input"]
    assert compute_crc(data, "crc32-iso-hdlc") == TEST_VECTOR["crc32-iso-hdlc"]
    assert compute_crc(data, "crc16-arc") == TEST_VECTOR["crc16-arc"]

    with tempfile.TemporaryDirectory() as temp_dir:
        sample_path = Path(temp_dir) / "sample.bin"
        sample_path.write_bytes(data)
        assert crc_file(sample_path, "crc32-iso-hdlc") == TEST_VECTOR["crc32-iso-hdlc"].upper()

    print("CRC tests passed")


if __name__ == "__main__":
    run_tests()