zrip-core 0.5.0

Shared types and codecs for zrip (internal crate)
Documentation
#[cfg(feature = "alloc")]
use alloc::vec::Vec;

#[cfg(all(target_arch = "x86_64", not(feature = "paranoid")))]
use super::CpuTier;

#[inline]
pub fn append_literals(dst: &mut Vec<u8>, src: &[u8]) {
    if src.is_empty() {
        return;
    }

    #[cfg(not(feature = "paranoid"))]
    {
        let len = src.len();
        dst.reserve(len + 32);
        let dst_offset = dst.len();

        #[cfg(target_arch = "x86_64")]
        {
            let tier = super::cpu_tier();
            if tier >= CpuTier::Avx2 && len >= 32 {
                unsafe {
                    let dst_ptr = dst.as_mut_ptr().add(dst_offset);
                    super::x86_64::avx2::wildcopy_avx2(src.as_ptr(), dst_ptr, len);
                    dst.set_len(dst_offset + len);
                }
                return;
            }
            if tier >= CpuTier::Sse2 && len >= 16 {
                unsafe {
                    let dst_ptr = dst.as_mut_ptr().add(dst_offset);
                    super::x86_64::sse2::wildcopy_sse2(src.as_ptr(), dst_ptr, len);
                    dst.set_len(dst_offset + len);
                }
                return;
            }
        }

        #[cfg(target_arch = "aarch64")]
        {
            if len >= 16 {
                unsafe {
                    let dst_ptr = dst.as_mut_ptr().add(dst_offset);
                    super::aarch64::neon::wildcopy_neon(src.as_ptr(), dst_ptr, len);
                    dst.set_len(dst_offset + len);
                }
                return;
            }
        }

        if len >= 8 {
            unsafe {
                let dst_ptr = dst.as_mut_ptr().add(dst_offset);
                super::scalar::wildcopy_nonoverlap(src.as_ptr(), dst_ptr, len);
                dst.set_len(dst_offset + len);
            }
        } else {
            dst.extend_from_slice(src);
        }
    }

    #[cfg(feature = "paranoid")]
    dst.extend_from_slice(src);
}

#[inline]
pub fn append_match(dst: &mut Vec<u8>, offset: usize, match_length: usize) {
    if match_length == 0 {
        return;
    }

    debug_assert!(offset <= dst.len());
    debug_assert!(offset > 0);

    #[cfg(not(feature = "paranoid"))]
    {
        dst.reserve(match_length + 32);
        let dst_len = dst.len();
        unsafe {
            let base = dst.as_mut_ptr();
            let write_ptr = base.add(dst_len);
            super::scalar::copy_match(write_ptr, offset, match_length);
            dst.set_len(dst_len + match_length);
        }
    }

    #[cfg(feature = "paranoid")]
    {
        dst.reserve(match_length);
        let start = dst.len() - offset;
        if offset >= match_length {
            let len = dst.len();
            dst.resize(len + match_length, 0);
            dst.copy_within(start..start + match_length, len);
        } else {
            for i in 0..match_length {
                let b = dst[start + i % offset];
                dst.push(b);
            }
        }
    }
}

#[inline]
pub fn common_prefix_len(a: &[u8], b: &[u8]) -> usize {
    #[cfg(all(target_arch = "x86_64", not(feature = "paranoid")))]
    {
        let tier = super::cpu_tier();
        if tier >= CpuTier::Avx2 && a.len() >= 32 && b.len() >= 32 {
            return unsafe { super::x86_64::avx2::common_prefix_len_avx2(a, b) };
        }
    }
    #[cfg(all(target_arch = "aarch64", not(feature = "paranoid")))]
    {
        if a.len() >= 16 && b.len() >= 16 {
            return unsafe { super::aarch64::neon::common_prefix_len_neon(a, b) };
        }
    }
    super::scalar::common_prefix_len(a, b)
}

#[inline]
pub fn append_match_with_history(
    dst: &mut Vec<u8>,
    history: &[u8],
    offset: usize,
    match_length: usize,
) {
    if match_length == 0 {
        return;
    }

    let out_len = dst.len();

    if offset <= out_len {
        append_match(dst, offset, match_length);
    } else {
        let history_reach = offset - out_len;
        let history_start = history.len() - history_reach;
        let from_history = history_reach.min(match_length);

        dst.extend_from_slice(&history[history_start..history_start + from_history]);

        let remaining = match_length - from_history;
        if remaining > 0 {
            append_match(dst, offset, remaining);
        }
    }
}