Skip to content

Commit e769337

Browse files
authored
feat: add crc_16_ibm_refin and crc_32_reversed_reciprocal_refin (#3)
1 parent 7251d55 commit e769337

File tree

4 files changed

+131
-16
lines changed

4 files changed

+131
-16
lines changed

fastcrc/crc16.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from .fastcrc import crc_16_umts as _crc_16_umts
3434
from .fastcrc import crc_16_usb as _crc_16_usb
3535
from .fastcrc import crc_16_xmodem as _crc_16_xmodem
36+
from .fastcrc import crc_16_ibm_refin as _crc_16_ibm_refin
3637
from .utils import _ensure_bytes
3738

3839
__always_supported = (
@@ -490,3 +491,19 @@ def xmodem(data: bytes, initial: Optional[int] = None) -> int:
490491
"""
491492
_ensure_bytes(data)
492493
return _crc_16_xmodem(data, initial)
494+
495+
496+
def ibm_refin(data: bytes, initial: Optional[int] = None) -> int:
497+
"""
498+
Compute a CRC-16 checksum of data with the ibm refin algorithm.
499+
500+
**This method may be removed in the future.**
501+
502+
:param bytes data: The data to be computed
503+
:param Optional[int] initial: The optional starting value of the checksum
504+
:return: The checksum
505+
:rtype: int
506+
:raises TypeError: if the data is not a bytes-like object
507+
"""
508+
_ensure_bytes(data)
509+
return _crc_16_ibm_refin(data, initial)

fastcrc/crc32.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
from .fastcrc import crc_32_jamcrc as _crc_32_jamcrc
1515
from .fastcrc import crc_32_mpeg_2 as _crc_32_mpeg_2
1616
from .fastcrc import crc_32_xfer as _crc_32_xfer
17+
from .fastcrc import (
18+
crc_32_reversed_reciprocal_refin as _crc_32_reversed_reciprocal_refin,
19+
)
1720
from .utils import _ensure_bytes
1821

1922
__always_supported = (
@@ -186,3 +189,19 @@ def xfer(data: bytes, initial: Optional[int] = None) -> int:
186189
"""
187190
_ensure_bytes(data)
188191
return _crc_32_xfer(data, initial)
192+
193+
194+
def reversed_reciprocal_refin(data: bytes, initial: Optional[int] = None) -> int:
195+
"""
196+
Compute a CRC-32 checksum of data with the reversed reciprocal refin algorithm.
197+
198+
**This method may be removed in the future.**
199+
200+
:param bytes data: The data to be computed
201+
:param Optional[int] initial: The optional starting value of the checksum
202+
:return: The checksum
203+
:rtype: int
204+
:raises TypeError: if the data is not a bytes-like object
205+
"""
206+
_ensure_bytes(data)
207+
return _crc_32_reversed_reciprocal_refin(data, initial)

src/lib.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crc::{
66
CRC_16_RIELLO, CRC_16_SPI_FUJITSU, CRC_16_T10_DIF, CRC_16_TELEDISK, CRC_16_TMS37157,
77
CRC_16_UMTS, CRC_16_USB, CRC_16_XMODEM, CRC_32_AIXM, CRC_32_AUTOSAR, CRC_32_BASE91_D,
88
CRC_32_BZIP2, CRC_32_CD_ROM_EDC, CRC_32_CKSUM, CRC_32_ISCSI, CRC_32_ISO_HDLC, CRC_32_JAMCRC,
9-
CRC_32_MPEG_2, CRC_32_XFER, CRC_64_ECMA_182, CRC_64_GO_ISO, CRC_64_WE, CRC_64_XZ,
9+
CRC_32_MPEG_2, CRC_32_XFER, CRC_64_ECMA_182, CRC_64_GO_ISO, CRC_64_WE, CRC_64_XZ, Algorithm
1010
};
1111
use pyo3::prelude::*;
1212
use pyo3::wrap_pyfunction;
@@ -24,7 +24,7 @@ macro_rules! define_crc_fn {
2424
None => CRC.digest(),
2525
Some(mut value) => {
2626
value ^= $crc_type.xorout;
27-
if $crc_type.refin {
27+
if $crc_type.refin && $crc_type.refout {
2828
value = value.reverse_bits()
2929
}
3030
CRC.digest_with_initial(value)
@@ -34,9 +34,31 @@ macro_rules! define_crc_fn {
3434
Ok(digest.finalize())
3535
}
3636
}
37-
}
37+
};
3838
}
3939

40+
const CRC_16_IBM_REFIN: Algorithm<u16> = Algorithm {
41+
width: 16,
42+
poly: 0x8005,
43+
init: 0xf0f0,
44+
refin: true,
45+
refout: false,
46+
xorout: 0x0000,
47+
check: 0x3cd0,
48+
residue: 0x0000
49+
};
50+
51+
const CRC_32_REVERSED_RECIPROCAL_REFIN: Algorithm<u32> = Algorithm {
52+
width: 32,
53+
poly: 0xba0dc66b,
54+
init: 0xf0f0f0f0,
55+
refin: true,
56+
refout: false,
57+
xorout: 0x00000000,
58+
check: 0x49ddfd79,
59+
residue: 0x00000000
60+
};
61+
4062
define_crc_fn!(crc_16_arc, u16, CRC_16_ARC);
4163
define_crc_fn!(crc_16_cdma2000, u16, CRC_16_CDMA2000);
4264
define_crc_fn!(crc_16_cms, u16, CRC_16_CMS);
@@ -67,6 +89,7 @@ define_crc_fn!(crc_16_tms37157, u16, CRC_16_TMS37157);
6789
define_crc_fn!(crc_16_umts, u16, CRC_16_UMTS);
6890
define_crc_fn!(crc_16_usb, u16, CRC_16_USB);
6991
define_crc_fn!(crc_16_xmodem, u16, CRC_16_XMODEM);
92+
define_crc_fn!(crc_16_ibm_refin, u16, CRC_16_IBM_REFIN);
7093
define_crc_fn!(crc_32_aixm, u32, CRC_32_AIXM);
7194
define_crc_fn!(crc_32_autosar, u32, CRC_32_AUTOSAR);
7295
define_crc_fn!(crc_32_base91_d, u32, CRC_32_BASE91_D);
@@ -78,6 +101,11 @@ define_crc_fn!(crc_32_iso_hdlc, u32, CRC_32_ISO_HDLC);
78101
define_crc_fn!(crc_32_jamcrc, u32, CRC_32_JAMCRC);
79102
define_crc_fn!(crc_32_mpeg_2, u32, CRC_32_MPEG_2);
80103
define_crc_fn!(crc_32_xfer, u32, CRC_32_XFER);
104+
define_crc_fn!(
105+
crc_32_reversed_reciprocal_refin,
106+
u32,
107+
CRC_32_REVERSED_RECIPROCAL_REFIN
108+
);
81109
define_crc_fn!(crc_64_ecma_182, u64, CRC_64_ECMA_182);
82110
define_crc_fn!(crc_64_go_iso, u64, CRC_64_GO_ISO);
83111
define_crc_fn!(crc_64_we, u64, CRC_64_WE);
@@ -115,6 +143,7 @@ fn fastcrc(_: Python, m: &PyModule) -> PyResult<()> {
115143
m.add_function(wrap_pyfunction!(crc_16_umts, m)?)?;
116144
m.add_function(wrap_pyfunction!(crc_16_usb, m)?)?;
117145
m.add_function(wrap_pyfunction!(crc_16_xmodem, m)?)?;
146+
m.add_function(wrap_pyfunction!(crc_16_ibm_refin, m)?)?;
118147
m.add_function(wrap_pyfunction!(crc_32_aixm, m)?)?;
119148
m.add_function(wrap_pyfunction!(crc_32_autosar, m)?)?;
120149
m.add_function(wrap_pyfunction!(crc_32_base91_d, m)?)?;
@@ -126,6 +155,7 @@ fn fastcrc(_: Python, m: &PyModule) -> PyResult<()> {
126155
m.add_function(wrap_pyfunction!(crc_32_jamcrc, m)?)?;
127156
m.add_function(wrap_pyfunction!(crc_32_mpeg_2, m)?)?;
128157
m.add_function(wrap_pyfunction!(crc_32_xfer, m)?)?;
158+
m.add_function(wrap_pyfunction!(crc_32_reversed_reciprocal_refin, m)?)?;
129159
m.add_function(wrap_pyfunction!(crc_64_ecma_182, m)?)?;
130160
m.add_function(wrap_pyfunction!(crc_64_go_iso, m)?)?;
131161
m.add_function(wrap_pyfunction!(crc_64_we, m)?)?;

tests/test_fastcrc.py

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,10 @@ def test_iso_iec_14443_3_a(self):
8484
self.assertEqual(48901, crc16.iso_iec_14443_3_a(data))
8585

8686
def test_iso_iec_14443_3_a_init(self):
87-
self.assertEqual(48901, crc16.iso_iec_14443_3_a(data_part2, crc16.iso_iec_14443_3_a(data_part1)))
87+
self.assertEqual(
88+
48901,
89+
crc16.iso_iec_14443_3_a(data_part2, crc16.iso_iec_14443_3_a(data_part1)),
90+
)
8891

8992
def test_kermit(self):
9093
self.assertEqual(8585, crc16.kermit(data))
@@ -102,7 +105,9 @@ def test_maxim_dow(self):
102105
self.assertEqual(17602, crc16.maxim_dow(data))
103106

104107
def test_maxim_dow_init(self):
105-
self.assertEqual(17602, crc16.maxim_dow(data_part2, crc16.maxim_dow(data_part1)))
108+
self.assertEqual(
109+
17602, crc16.maxim_dow(data_part2, crc16.maxim_dow(data_part1))
110+
)
106111

107112
def test_mcrf4xx(self):
108113
self.assertEqual(28561, crc16.mcrf4xx(data))
@@ -126,13 +131,17 @@ def test_opensafety_a(self):
126131
self.assertEqual(23864, crc16.opensafety_a(data))
127132

128133
def test_opensafety_a_init(self):
129-
self.assertEqual(23864, crc16.opensafety_a(data_part2, crc16.opensafety_a(data_part1)))
134+
self.assertEqual(
135+
23864, crc16.opensafety_a(data_part2, crc16.opensafety_a(data_part1))
136+
)
130137

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

134141
def test_opensafety_b_init(self):
135-
self.assertEqual(8446, crc16.opensafety_b(data_part2, crc16.opensafety_b(data_part1)))
142+
self.assertEqual(
143+
8446, crc16.opensafety_b(data_part2, crc16.opensafety_b(data_part1))
144+
)
136145

137146
def test_profibus(self):
138147
self.assertEqual(43033, crc16.profibus(data))
@@ -150,7 +159,9 @@ def test_spi_fujitsu(self):
150159
self.assertEqual(58828, crc16.spi_fujitsu(data))
151160

152161
def test_spi_fujitsu_init(self):
153-
self.assertEqual(58828, crc16.spi_fujitsu(data_part2, crc16.spi_fujitsu(data_part1)))
162+
self.assertEqual(
163+
58828, crc16.spi_fujitsu(data_part2, crc16.spi_fujitsu(data_part1))
164+
)
154165

155166
def test_t10_dif(self):
156167
self.assertEqual(53467, crc16.t10_dif(data))
@@ -188,6 +199,14 @@ def test_xmodem(self):
188199
def test_xmodem_init(self):
189200
self.assertEqual(12739, crc16.xmodem(data_part2, crc16.xmodem(data_part1)))
190201

202+
def test_ibm_refin(self):
203+
self.assertEqual(15568, crc16.ibm_refin(data))
204+
205+
def test_ibm_refin_init(self):
206+
self.assertEqual(
207+
15568, crc16.ibm_refin(data_part2, crc16.ibm_refin(data_part1))
208+
)
209+
191210

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

202221
def test_autosar_init(self):
203-
self.assertEqual(379048042, crc32.autosar(data_part2, crc32.autosar(data_part1)))
222+
self.assertEqual(
223+
379048042, crc32.autosar(data_part2, crc32.autosar(data_part1))
224+
)
204225

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

208229
def test_base91_d_init(self):
209-
self.assertEqual(2268157302, crc32.base91_d(data_part2, crc32.base91_d(data_part1)))
230+
self.assertEqual(
231+
2268157302, crc32.base91_d(data_part2, crc32.base91_d(data_part1))
232+
)
210233

211234
def test_bzip2(self):
212235
self.assertEqual(4236843288, crc32.bzip2(data))
@@ -218,7 +241,9 @@ def test_cd_rom_edc(self):
218241
self.assertEqual(1858268612, crc32.cd_rom_edc(data))
219242

220243
def test_cd_rom_edc_init(self):
221-
self.assertEqual(1858268612, crc32.cd_rom_edc(data_part2, crc32.cd_rom_edc(data_part1)))
244+
self.assertEqual(
245+
1858268612, crc32.cd_rom_edc(data_part2, crc32.cd_rom_edc(data_part1))
246+
)
222247

223248
def test_cksum(self):
224249
self.assertEqual(1985902208, crc32.cksum(data))
@@ -236,7 +261,9 @@ def test_iso_hdlc(self):
236261
self.assertEqual(3421780262, crc32.iso_hdlc(data))
237262

238263
def test_iso_hdlc_init(self):
239-
self.assertEqual(3421780262, crc32.iso_hdlc(data_part2, crc32.iso_hdlc(data_part1)))
264+
self.assertEqual(
265+
3421780262, crc32.iso_hdlc(data_part2, crc32.iso_hdlc(data_part1))
266+
)
240267

241268
def test_jamcrc(self):
242269
self.assertEqual(873187033, crc32.jamcrc(data))
@@ -256,31 +283,53 @@ def test_xfer(self):
256283
def test_xfer_init(self):
257284
self.assertEqual(3171672888, crc32.xfer(data_part2, crc32.xfer(data_part1)))
258285

286+
def test_reversed_reciprocal_refin(self):
287+
self.assertEqual(
288+
1239285113,
289+
crc32.reversed_reciprocal_refin(data),
290+
)
291+
292+
def test_reversed_reciprocal_refin_init(self):
293+
self.assertEqual(
294+
1239285113,
295+
crc32.reversed_reciprocal_refin(
296+
data_part2, crc32.reversed_reciprocal_refin(data_part1)
297+
),
298+
)
299+
259300

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

264305
def test_ecma_182_init(self):
265-
self.assertEqual(7800480153909949255, crc64.ecma_182(data_part2, crc64.ecma_182(data_part1)))
306+
self.assertEqual(
307+
7800480153909949255, crc64.ecma_182(data_part2, crc64.ecma_182(data_part1))
308+
)
266309

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

270313
def test_go_iso_init(self):
271-
self.assertEqual(13333283586479230977, crc64.go_iso(data_part2, crc64.go_iso(data_part1)))
314+
self.assertEqual(
315+
13333283586479230977, crc64.go_iso(data_part2, crc64.go_iso(data_part1))
316+
)
272317

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

276321
def test_we_init(self):
277-
self.assertEqual(7128171145767219210, crc64.we(data_part2, crc64.we(data_part1)))
322+
self.assertEqual(
323+
7128171145767219210, crc64.we(data_part2, crc64.we(data_part1))
324+
)
278325

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

282329
def test_xz_init(self):
283-
self.assertEqual(11051210869376104954, crc64.xz(data_part2, crc64.xz(data_part1)))
330+
self.assertEqual(
331+
11051210869376104954, crc64.xz(data_part2, crc64.xz(data_part1))
332+
)
284333

285334

286335
if __name__ == "__main__":

0 commit comments

Comments
 (0)