Skip to content

Commit

Permalink
feat: add crc_16_ibm_refin and crc_32_reversed_reciprocal_refin (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
overcat authored Sep 14, 2022
1 parent 7251d55 commit e769337
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 16 deletions.
17 changes: 17 additions & 0 deletions fastcrc/crc16.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from .fastcrc import crc_16_umts as _crc_16_umts
from .fastcrc import crc_16_usb as _crc_16_usb
from .fastcrc import crc_16_xmodem as _crc_16_xmodem
from .fastcrc import crc_16_ibm_refin as _crc_16_ibm_refin
from .utils import _ensure_bytes

__always_supported = (
Expand Down Expand Up @@ -490,3 +491,19 @@ def xmodem(data: bytes, initial: Optional[int] = None) -> int:
"""
_ensure_bytes(data)
return _crc_16_xmodem(data, initial)


def ibm_refin(data: bytes, initial: Optional[int] = None) -> int:
"""
Compute a CRC-16 checksum of data with the ibm refin algorithm.
**This method may be removed in the future.**
:param bytes data: The data to be computed
:param Optional[int] initial: The optional starting value of the checksum
:return: The checksum
:rtype: int
:raises TypeError: if the data is not a bytes-like object
"""
_ensure_bytes(data)
return _crc_16_ibm_refin(data, initial)
19 changes: 19 additions & 0 deletions fastcrc/crc32.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
from .fastcrc import crc_32_jamcrc as _crc_32_jamcrc
from .fastcrc import crc_32_mpeg_2 as _crc_32_mpeg_2
from .fastcrc import crc_32_xfer as _crc_32_xfer
from .fastcrc import (
crc_32_reversed_reciprocal_refin as _crc_32_reversed_reciprocal_refin,
)
from .utils import _ensure_bytes

__always_supported = (
Expand Down Expand Up @@ -186,3 +189,19 @@ def xfer(data: bytes, initial: Optional[int] = None) -> int:
"""
_ensure_bytes(data)
return _crc_32_xfer(data, initial)


def reversed_reciprocal_refin(data: bytes, initial: Optional[int] = None) -> int:
"""
Compute a CRC-32 checksum of data with the reversed reciprocal refin algorithm.
**This method may be removed in the future.**
:param bytes data: The data to be computed
:param Optional[int] initial: The optional starting value of the checksum
:return: The checksum
:rtype: int
:raises TypeError: if the data is not a bytes-like object
"""
_ensure_bytes(data)
return _crc_32_reversed_reciprocal_refin(data, initial)
36 changes: 33 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crc::{
CRC_16_RIELLO, CRC_16_SPI_FUJITSU, CRC_16_T10_DIF, CRC_16_TELEDISK, CRC_16_TMS37157,
CRC_16_UMTS, CRC_16_USB, CRC_16_XMODEM, CRC_32_AIXM, CRC_32_AUTOSAR, CRC_32_BASE91_D,
CRC_32_BZIP2, CRC_32_CD_ROM_EDC, CRC_32_CKSUM, CRC_32_ISCSI, CRC_32_ISO_HDLC, CRC_32_JAMCRC,
CRC_32_MPEG_2, CRC_32_XFER, CRC_64_ECMA_182, CRC_64_GO_ISO, CRC_64_WE, CRC_64_XZ,
CRC_32_MPEG_2, CRC_32_XFER, CRC_64_ECMA_182, CRC_64_GO_ISO, CRC_64_WE, CRC_64_XZ, Algorithm
};
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
Expand All @@ -24,7 +24,7 @@ macro_rules! define_crc_fn {
None => CRC.digest(),
Some(mut value) => {
value ^= $crc_type.xorout;
if $crc_type.refin {
if $crc_type.refin && $crc_type.refout {
value = value.reverse_bits()
}
CRC.digest_with_initial(value)
Expand All @@ -34,9 +34,31 @@ macro_rules! define_crc_fn {
Ok(digest.finalize())
}
}
}
};
}

const CRC_16_IBM_REFIN: Algorithm<u16> = Algorithm {
width: 16,
poly: 0x8005,
init: 0xf0f0,
refin: true,
refout: false,
xorout: 0x0000,
check: 0x3cd0,
residue: 0x0000
};

const CRC_32_REVERSED_RECIPROCAL_REFIN: Algorithm<u32> = Algorithm {
width: 32,
poly: 0xba0dc66b,
init: 0xf0f0f0f0,
refin: true,
refout: false,
xorout: 0x00000000,
check: 0x49ddfd79,
residue: 0x00000000
};

define_crc_fn!(crc_16_arc, u16, CRC_16_ARC);
define_crc_fn!(crc_16_cdma2000, u16, CRC_16_CDMA2000);
define_crc_fn!(crc_16_cms, u16, CRC_16_CMS);
Expand Down Expand Up @@ -67,6 +89,7 @@ define_crc_fn!(crc_16_tms37157, u16, CRC_16_TMS37157);
define_crc_fn!(crc_16_umts, u16, CRC_16_UMTS);
define_crc_fn!(crc_16_usb, u16, CRC_16_USB);
define_crc_fn!(crc_16_xmodem, u16, CRC_16_XMODEM);
define_crc_fn!(crc_16_ibm_refin, u16, CRC_16_IBM_REFIN);
define_crc_fn!(crc_32_aixm, u32, CRC_32_AIXM);
define_crc_fn!(crc_32_autosar, u32, CRC_32_AUTOSAR);
define_crc_fn!(crc_32_base91_d, u32, CRC_32_BASE91_D);
Expand All @@ -78,6 +101,11 @@ define_crc_fn!(crc_32_iso_hdlc, u32, CRC_32_ISO_HDLC);
define_crc_fn!(crc_32_jamcrc, u32, CRC_32_JAMCRC);
define_crc_fn!(crc_32_mpeg_2, u32, CRC_32_MPEG_2);
define_crc_fn!(crc_32_xfer, u32, CRC_32_XFER);
define_crc_fn!(
crc_32_reversed_reciprocal_refin,
u32,
CRC_32_REVERSED_RECIPROCAL_REFIN
);
define_crc_fn!(crc_64_ecma_182, u64, CRC_64_ECMA_182);
define_crc_fn!(crc_64_go_iso, u64, CRC_64_GO_ISO);
define_crc_fn!(crc_64_we, u64, CRC_64_WE);
Expand Down Expand Up @@ -115,6 +143,7 @@ fn fastcrc(_: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(crc_16_umts, m)?)?;
m.add_function(wrap_pyfunction!(crc_16_usb, m)?)?;
m.add_function(wrap_pyfunction!(crc_16_xmodem, m)?)?;
m.add_function(wrap_pyfunction!(crc_16_ibm_refin, m)?)?;
m.add_function(wrap_pyfunction!(crc_32_aixm, m)?)?;
m.add_function(wrap_pyfunction!(crc_32_autosar, m)?)?;
m.add_function(wrap_pyfunction!(crc_32_base91_d, m)?)?;
Expand All @@ -126,6 +155,7 @@ fn fastcrc(_: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(crc_32_jamcrc, m)?)?;
m.add_function(wrap_pyfunction!(crc_32_mpeg_2, m)?)?;
m.add_function(wrap_pyfunction!(crc_32_xfer, m)?)?;
m.add_function(wrap_pyfunction!(crc_32_reversed_reciprocal_refin, m)?)?;
m.add_function(wrap_pyfunction!(crc_64_ecma_182, m)?)?;
m.add_function(wrap_pyfunction!(crc_64_go_iso, m)?)?;
m.add_function(wrap_pyfunction!(crc_64_we, m)?)?;
Expand Down
75 changes: 62 additions & 13 deletions tests/test_fastcrc.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ def test_iso_iec_14443_3_a(self):
self.assertEqual(48901, crc16.iso_iec_14443_3_a(data))

def test_iso_iec_14443_3_a_init(self):
self.assertEqual(48901, crc16.iso_iec_14443_3_a(data_part2, crc16.iso_iec_14443_3_a(data_part1)))
self.assertEqual(
48901,
crc16.iso_iec_14443_3_a(data_part2, crc16.iso_iec_14443_3_a(data_part1)),
)

def test_kermit(self):
self.assertEqual(8585, crc16.kermit(data))
Expand All @@ -102,7 +105,9 @@ def test_maxim_dow(self):
self.assertEqual(17602, crc16.maxim_dow(data))

def test_maxim_dow_init(self):
self.assertEqual(17602, crc16.maxim_dow(data_part2, crc16.maxim_dow(data_part1)))
self.assertEqual(
17602, crc16.maxim_dow(data_part2, crc16.maxim_dow(data_part1))
)

def test_mcrf4xx(self):
self.assertEqual(28561, crc16.mcrf4xx(data))
Expand All @@ -126,13 +131,17 @@ def test_opensafety_a(self):
self.assertEqual(23864, crc16.opensafety_a(data))

def test_opensafety_a_init(self):
self.assertEqual(23864, crc16.opensafety_a(data_part2, crc16.opensafety_a(data_part1)))
self.assertEqual(
23864, crc16.opensafety_a(data_part2, crc16.opensafety_a(data_part1))
)

def test_opensafety_b(self):
self.assertEqual(8446, crc16.opensafety_b(data))

def test_opensafety_b_init(self):
self.assertEqual(8446, crc16.opensafety_b(data_part2, crc16.opensafety_b(data_part1)))
self.assertEqual(
8446, crc16.opensafety_b(data_part2, crc16.opensafety_b(data_part1))
)

def test_profibus(self):
self.assertEqual(43033, crc16.profibus(data))
Expand All @@ -150,7 +159,9 @@ def test_spi_fujitsu(self):
self.assertEqual(58828, crc16.spi_fujitsu(data))

def test_spi_fujitsu_init(self):
self.assertEqual(58828, crc16.spi_fujitsu(data_part2, crc16.spi_fujitsu(data_part1)))
self.assertEqual(
58828, crc16.spi_fujitsu(data_part2, crc16.spi_fujitsu(data_part1))
)

def test_t10_dif(self):
self.assertEqual(53467, crc16.t10_dif(data))
Expand Down Expand Up @@ -188,6 +199,14 @@ def test_xmodem(self):
def test_xmodem_init(self):
self.assertEqual(12739, crc16.xmodem(data_part2, crc16.xmodem(data_part1)))

def test_ibm_refin(self):
self.assertEqual(15568, crc16.ibm_refin(data))

def test_ibm_refin_init(self):
self.assertEqual(
15568, crc16.ibm_refin(data_part2, crc16.ibm_refin(data_part1))
)


class TestCrc32(unittest.TestCase):
def test_aixm(self):
Expand All @@ -200,13 +219,17 @@ def test_autosar(self):
self.assertEqual(379048042, crc32.autosar(data))

def test_autosar_init(self):
self.assertEqual(379048042, crc32.autosar(data_part2, crc32.autosar(data_part1)))
self.assertEqual(
379048042, crc32.autosar(data_part2, crc32.autosar(data_part1))
)

def test_base91_d(self):
self.assertEqual(2268157302, crc32.base91_d(data))

def test_base91_d_init(self):
self.assertEqual(2268157302, crc32.base91_d(data_part2, crc32.base91_d(data_part1)))
self.assertEqual(
2268157302, crc32.base91_d(data_part2, crc32.base91_d(data_part1))
)

def test_bzip2(self):
self.assertEqual(4236843288, crc32.bzip2(data))
Expand All @@ -218,7 +241,9 @@ def test_cd_rom_edc(self):
self.assertEqual(1858268612, crc32.cd_rom_edc(data))

def test_cd_rom_edc_init(self):
self.assertEqual(1858268612, crc32.cd_rom_edc(data_part2, crc32.cd_rom_edc(data_part1)))
self.assertEqual(
1858268612, crc32.cd_rom_edc(data_part2, crc32.cd_rom_edc(data_part1))
)

def test_cksum(self):
self.assertEqual(1985902208, crc32.cksum(data))
Expand All @@ -236,7 +261,9 @@ def test_iso_hdlc(self):
self.assertEqual(3421780262, crc32.iso_hdlc(data))

def test_iso_hdlc_init(self):
self.assertEqual(3421780262, crc32.iso_hdlc(data_part2, crc32.iso_hdlc(data_part1)))
self.assertEqual(
3421780262, crc32.iso_hdlc(data_part2, crc32.iso_hdlc(data_part1))
)

def test_jamcrc(self):
self.assertEqual(873187033, crc32.jamcrc(data))
Expand All @@ -256,31 +283,53 @@ def test_xfer(self):
def test_xfer_init(self):
self.assertEqual(3171672888, crc32.xfer(data_part2, crc32.xfer(data_part1)))

def test_reversed_reciprocal_refin(self):
self.assertEqual(
1239285113,
crc32.reversed_reciprocal_refin(data),
)

def test_reversed_reciprocal_refin_init(self):
self.assertEqual(
1239285113,
crc32.reversed_reciprocal_refin(
data_part2, crc32.reversed_reciprocal_refin(data_part1)
),
)


class TestCrc64(unittest.TestCase):
def test_ecma_182(self):
self.assertEqual(7800480153909949255, crc64.ecma_182(data))

def test_ecma_182_init(self):
self.assertEqual(7800480153909949255, crc64.ecma_182(data_part2, crc64.ecma_182(data_part1)))
self.assertEqual(
7800480153909949255, crc64.ecma_182(data_part2, crc64.ecma_182(data_part1))
)

def test_go_iso(self):
self.assertEqual(13333283586479230977, crc64.go_iso(data))

def test_go_iso_init(self):
self.assertEqual(13333283586479230977, crc64.go_iso(data_part2, crc64.go_iso(data_part1)))
self.assertEqual(
13333283586479230977, crc64.go_iso(data_part2, crc64.go_iso(data_part1))
)

def test_we(self):
self.assertEqual(7128171145767219210, crc64.we(data))

def test_we_init(self):
self.assertEqual(7128171145767219210, crc64.we(data_part2, crc64.we(data_part1)))
self.assertEqual(
7128171145767219210, crc64.we(data_part2, crc64.we(data_part1))
)

def test_xz(self):
self.assertEqual(11051210869376104954, crc64.xz(data))

def test_xz_init(self):
self.assertEqual(11051210869376104954, crc64.xz(data_part2, crc64.xz(data_part1)))
self.assertEqual(
11051210869376104954, crc64.xz(data_part2, crc64.xz(data_part1))
)


if __name__ == "__main__":
Expand Down

0 comments on commit e769337

Please sign in to comment.