Skip to content

Commit 0e95888

Browse files
committed
add specific tests for copy_match
1 parent e67872b commit 0e95888

File tree

1 file changed

+99
-5
lines changed

1 file changed

+99
-5
lines changed

zlib-rs/src/inflate/writer.rs

+99-5
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,9 @@ impl<'a> Writer<'a> {
176176
end: usize,
177177
) {
178178
if (end - start).next_multiple_of(core::mem::size_of::<C>()) <= (buf.len() - current) {
179+
let ptr = buf.as_mut_ptr();
179180
unsafe {
180-
Self::copy_chunk_unchecked::<C>(
181-
buf.as_ptr().add(start),
182-
buf.as_mut_ptr().add(current),
183-
buf.as_ptr().add(end),
184-
)
181+
Self::copy_chunk_unchecked::<C>(ptr.add(start), ptr.add(current), ptr.add(end))
185182
}
186183
} else {
187184
// a full simd copy does not fit in the output buffer
@@ -300,3 +297,100 @@ impl Chunk for core::arch::x86_64::__m512i {
300297
core::ptr::write_unaligned(out.cast(), chunk)
301298
}
302299
}
300+
301+
#[cfg(test)]
302+
mod test {
303+
use super::*;
304+
305+
const N: usize = 128;
306+
const M: usize = 64;
307+
308+
fn test_array() -> [MaybeUninit<u8>; N] {
309+
core::array::from_fn(|i| MaybeUninit::new(if i < M { i as u8 } else { 0xAAu8 }))
310+
}
311+
312+
fn test_copy_match(offset_from_end: usize, length: usize) {
313+
let mut buf = test_array();
314+
let mut writer = Writer {
315+
buf: &mut buf,
316+
filled: M,
317+
};
318+
writer.copy_match(offset_from_end, length);
319+
assert_eq!(writer.filled, M + length);
320+
321+
let mut naive = test_array();
322+
for i in 0..length {
323+
naive[M + i] = naive[M - offset_from_end + i];
324+
}
325+
326+
let buf = unsafe { core::mem::transmute::<[MaybeUninit<u8>; 128], [u8; N]>(buf) };
327+
let naive = unsafe { core::mem::transmute::<[MaybeUninit<u8>; 128], [u8; N]>(naive) };
328+
assert_eq!(
329+
buf[M..][..length],
330+
naive[M..][..length],
331+
"{} {}",
332+
offset_from_end,
333+
length
334+
);
335+
}
336+
337+
#[test]
338+
fn copy_chunk_unchecked() {
339+
let offset_from_end = 17;
340+
let length = 17;
341+
342+
#[cfg(target_arch = "x86_64")]
343+
use core::arch::x86_64::{__m128i, __m256i, __m512i};
344+
345+
macro_rules! helper {
346+
($func:expr) => {
347+
let mut buf = test_array();
348+
let mut writer = Writer {
349+
buf: &mut buf,
350+
filled: M,
351+
};
352+
353+
$func(&mut writer, offset_from_end, length);
354+
};
355+
}
356+
357+
#[cfg(target_arch = "x86_64")]
358+
if crate::cpu_features::is_enabled_avx512() {
359+
helper!(Writer::copy_match_help::<__m512i>);
360+
}
361+
362+
#[cfg(target_arch = "x86_64")]
363+
if crate::cpu_features::is_enabled_avx2() {
364+
helper!(Writer::copy_match_help::<__m256i>);
365+
}
366+
367+
#[cfg(target_arch = "x86_64")]
368+
if crate::cpu_features::is_enabled_sse() {
369+
helper!(Writer::copy_match_help::<__m128i>);
370+
}
371+
372+
helper!(Writer::copy_match_help::<u64>);
373+
}
374+
375+
#[test]
376+
fn copy_match() {
377+
for offset_from_end in 1..=64 {
378+
for length in 0..=64 {
379+
test_copy_match(offset_from_end, length)
380+
}
381+
}
382+
}
383+
384+
#[test]
385+
fn copy_match_insufficient_space_for_simd() {
386+
let mut buf = [1, 2, 3, 0xAA, 0xAA].map(MaybeUninit::new);
387+
let mut writer = Writer {
388+
buf: &mut buf,
389+
filled: 3,
390+
};
391+
392+
writer.copy_match(3, 2);
393+
394+
assert_eq!(buf.map(|e| unsafe { e.assume_init() }), [1, 2, 3, 1, 2]);
395+
}
396+
}

0 commit comments

Comments
 (0)