Skip to content

Commit 52c26f6

Browse files
committed
use as_chunks for adler32 generic version
1 parent c26205b commit 52c26f6

1 file changed

Lines changed: 38 additions & 5 deletions

File tree

zlib-rs/src/adler32/generic.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,10 @@ pub fn adler32_rust(mut adler: u32, buf: &[u8]) -> u32 {
6060
return adler32_len_16(adler, buf, sum2);
6161
}
6262

63-
let mut it = buf.chunks_exact(NMAX as usize);
64-
for big_chunk in it.by_ref() {
63+
let (big_chunks, rest) = slice_as_chunks::<_, { NMAX as usize }>(buf);
64+
for big_chunk in big_chunks {
6565
const N: usize = if UNROLL_MORE { 16 } else { 8 } as usize;
66-
let it = big_chunk.chunks_exact(N);
67-
for chunk in it {
66+
for chunk in slice_as_chunks::<_, N>(big_chunk).0 {
6867
if N == 16 {
6968
do16!(adler, sum2, chunk);
7069
} else {
@@ -77,7 +76,7 @@ pub fn adler32_rust(mut adler: u32, buf: &[u8]) -> u32 {
7776
}
7877

7978
/* do remaining bytes (less than NMAX, still just one modulo) */
80-
adler32_len_64(adler, it.remainder(), sum2)
79+
adler32_len_64(adler, rest, sum2)
8180
}
8281

8382
pub(crate) fn adler32_len_1(mut adler: u32, buf: &[u8], mut sum2: u32) -> u32 {
@@ -114,3 +113,37 @@ pub(crate) fn adler32_len_64(mut adler: u32, buf: &[u8], mut sum2: u32) -> u32 {
114113
/* Process tail (len < 16). */
115114
adler32_len_16(adler, it.remainder(), sum2)
116115
}
116+
117+
// FIXME use the method on slices once available.
118+
fn slice_as_chunks<T, const N: usize>(slice: &[T]) -> (&[[T; N]], &[T]) {
119+
assert!(N != 0, "chunk size must be non-zero");
120+
let len_rounded_down = slice.len() / N * N;
121+
// SAFETY: The rounded-down value is always the same or smaller than the
122+
// original length, and thus must be in-bounds of the slice.
123+
let (multiple_of_n, remainder) = unsafe { slice_split_at_unchecked(slice, len_rounded_down) };
124+
// SAFETY: We already panicked for zero, and ensured by construction
125+
// that the length of the subslice is a multiple of N.
126+
let array_slice = unsafe { slice_as_chunks_unchecked(multiple_of_n) };
127+
(array_slice, remainder)
128+
}
129+
130+
unsafe fn slice_as_chunks_unchecked<T, const N: usize>(slice: &[T]) -> &[[T; N]] {
131+
// SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
132+
let new_len = slice.len() / N;
133+
// SAFETY: We cast a slice of `new_len * N` elements into
134+
// a slice of `new_len` many `N` elements chunks.
135+
unsafe { core::slice::from_raw_parts(slice.as_ptr().cast(), new_len) }
136+
}
137+
138+
pub unsafe fn slice_split_at_unchecked<T>(slice: &[T], mid: usize) -> (&[T], &[T]) {
139+
let len = slice.len();
140+
let ptr = slice.as_ptr();
141+
142+
// SAFETY: Caller has to check that `0 <= mid <= self.len()`
143+
unsafe {
144+
(
145+
core::slice::from_raw_parts(ptr, mid),
146+
core::slice::from_raw_parts(ptr.add(mid), len - mid),
147+
)
148+
}
149+
}

0 commit comments

Comments
 (0)