@@ -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
8382pub ( 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