Skip to content

Commit 1e81ae5

Browse files
committed
add missing crc32 helpers
1 parent 28320ef commit 1e81ae5

File tree

4 files changed

+86
-3
lines changed

4 files changed

+86
-3
lines changed

libz-rs-sys/src/lib.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,30 @@ pub extern "C" fn get_crc_table() -> *const [u32; 256] {
243243
zlib_rs::get_crc_table()
244244
}
245245

246+
/// Return the operator corresponding to length `len2`, to be used with
247+
/// [`crc32_combine_op`]. `len2` must be non-negative.
248+
#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_combine_gen64))]
249+
pub const extern "C" fn crc32_combine_gen64(len2: z_off64_t) -> c_ulong {
250+
debug_assert!(len2 >= 0, "`len2` must be non-negative");
251+
zlib_rs::crc32::crc32_combine_gen(len2 as u64) as c_ulong
252+
}
253+
254+
/// Return the operator corresponding to length `len2`, to be used with
255+
/// [`crc32_combine_op`]. `len2` must be non-negative.
256+
#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_combine_gen))]
257+
pub const extern "C" fn crc32_combine_gen(len2: z_off_t) -> c_ulong {
258+
debug_assert!(len2 >= 0, "`len2` must be non-negative");
259+
zlib_rs::crc32::crc32_combine_gen(len2 as u64) as c_ulong
260+
}
261+
262+
/// Give the same result as [`crc32_combine`], using `op` in place of `len2`.
263+
/// `op` is is generated from `len2` by [`crc32_combine_gen`].
264+
/// This will be faster than [`crc32_combine`] if the generated `op` is used more than once.
265+
#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_combine_op))]
266+
pub const extern "C" fn crc32_combine_op(crc1: c_ulong, crc2: c_ulong, op: c_ulong) -> c_ulong {
267+
zlib_rs::crc32::crc32_combine_op(crc1 as u32, crc2 as u32, op as u32) as c_ulong
268+
}
269+
246270
/// Calculates the [adler32](https://en.wikipedia.org/wiki/Adler-32) checksum
247271
/// of a sequence of bytes.
248272
///

test-libz-rs-sys/src/lib.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ macro_rules! assert_eq_rs_ng {
5959
len2: libz_rs_sys::z_off64_t,
6060
) -> core::ffi::c_ulong;
6161

62+
#[allow(unused)]
63+
fn crc32_combine_gen(len2: z_off_t) -> core::ffi::c_ulong;
64+
65+
#[allow(unused)]
66+
fn crc32_combine_op(
67+
crc1: core::ffi::c_ulong,
68+
crc2: core::ffi::c_ulong,
69+
op: core::ffi::c_ulong,
70+
) -> core::ffi::c_ulong;
71+
6272
#[allow(unused)]
6373
fn adler32_z(
6474
crc: core::ffi::c_ulong,
@@ -192,6 +202,55 @@ mod null {
192202
assert_eq!(libz_rs_sys::crc32_combine(2, 123, -16), 2171032315);
193203
}
194204

205+
#[test]
206+
fn test_crc32_combine() {
207+
::quickcheck::quickcheck(test as fn(_) -> _);
208+
209+
fn test(data: Vec<u8>) -> bool {
210+
let Some(buf_len) = data.first().copied() else {
211+
return true;
212+
};
213+
214+
let buf_size = Ord::max(buf_len, 1) as usize;
215+
216+
assert_eq_rs_ng!({
217+
let crc0 = 0;
218+
let mut crc1 = crc0;
219+
let mut crc2 = crc0;
220+
221+
/* CRC32 */
222+
for chunk in data.chunks(buf_size) {
223+
let crc3 = crc32(crc0, chunk.as_ptr(), chunk.len() as _);
224+
let op = crc32_combine_gen(chunk.len() as _);
225+
let crc4 = crc32_combine_op(crc1, crc3, op);
226+
crc1 = crc32(crc1, chunk.as_ptr(), chunk.len() as _);
227+
228+
assert_eq!(crc1, crc4);
229+
}
230+
231+
crc2 = crc32(crc2, data.as_ptr(), data.len() as _);
232+
233+
assert_eq!(crc1, crc2);
234+
235+
let combine1 = crc32_combine(crc1, crc2, data.len() as _);
236+
let combine2 = crc32_combine(crc1, crc1, data.len() as _);
237+
assert_eq!(combine1, combine2);
238+
239+
// Fast CRC32 combine.
240+
let op = crc32_combine_gen(data.len() as _);
241+
let combine1 = crc32_combine_op(crc1, crc2, op);
242+
let combine2 = crc32_combine_op(crc2, crc1, op);
243+
assert_eq!(combine1, combine2);
244+
245+
let combine1 = crc32_combine(crc1, crc2, data.len() as _);
246+
let combine2 = crc32_combine_op(crc2, crc1, op);
247+
assert_eq!(combine1, combine2);
248+
});
249+
250+
true
251+
}
252+
}
253+
195254
#[test]
196255
fn uncompress() {
197256
let mut dest = [0; 64];

zlib-rs/src/crc32.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod pclmulqdq;
1010
#[cfg(feature = "vpclmulqdq")]
1111
mod vpclmulqdq;
1212

13-
pub use combine::crc32_combine;
13+
pub use combine::{crc32_combine, crc32_combine_gen, crc32_combine_op};
1414

1515
pub fn crc32(start: u32, buf: &[u8]) -> u32 {
1616
/* For lens < 64, crc32_braid method is faster. The CRC32 instruction for

zlib-rs/src/crc32/combine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ pub const fn crc32_combine(crc1: u32, crc2: u32, len2: u64) -> u32 {
55
}
66

77
#[inline(always)]
8-
const fn crc32_combine_gen(len2: u64) -> u32 {
8+
pub const fn crc32_combine_gen(len2: u64) -> u32 {
99
x2nmodp(len2, 3)
1010
}
1111

1212
#[inline(always)]
13-
const fn crc32_combine_op(crc1: u32, crc2: u32, op: u32) -> u32 {
13+
pub const fn crc32_combine_op(crc1: u32, crc2: u32, op: u32) -> u32 {
1414
multmodp(op, crc1) ^ crc2
1515
}
1616

0 commit comments

Comments
 (0)