libzstd-rs-sys 0.0.0

a rust implementation of zstd compression and decompression
Documentation
use core::ptr;

use libc::size_t;

use crate::lib::common::mem::MEM_read16;
use crate::lib::compress::hist::HIST_add;

#[repr(C)]
pub struct Fingerprint {
    pub events: [core::ffi::c_uint; 1024],
    pub nbEvents: size_t,
}
#[repr(C)]
pub struct FPStats {
    pub pastEvents: Fingerprint,
    pub newEvents: Fingerprint,
}
pub type RecordEvents_f =
    Option<unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> ()>;
pub const THRESHOLD_PENALTY_RATE: core::ffi::c_int = 16;
pub const THRESHOLD_BASE: core::ffi::c_int = THRESHOLD_PENALTY_RATE - 2;
pub const THRESHOLD_PENALTY: core::ffi::c_int = 3;
pub const HASHLENGTH: core::ffi::c_int = 2;
pub const HASHLOG_MAX: core::ffi::c_int = 10;
pub const HASHTABLESIZE: core::ffi::c_int = (1) << HASHLOG_MAX;
pub const KNUTH: core::ffi::c_uint = 0x9e3779b9;
#[inline(always)]
unsafe fn hash2(p: *const core::ffi::c_void, hashLog: core::ffi::c_uint) -> core::ffi::c_uint {
    if hashLog == 8 {
        return *(p as *const u8).offset(0) as u32;
    }
    (MEM_read16(p) as u32).wrapping_mul(KNUTH) >> (32 as core::ffi::c_uint).wrapping_sub(hashLog)
}
unsafe fn initStats(fpstats: *mut FPStats) {
    ptr::write_bytes(fpstats as *mut u8, 0, ::core::mem::size_of::<FPStats>());
}
#[inline(always)]
unsafe fn addEvents_generic(
    fp: *mut Fingerprint,
    src: *const core::ffi::c_void,
    srcSize: size_t,
    samplingRate: size_t,
    hashLog: core::ffi::c_uint,
) {
    let p = src as *const core::ffi::c_char;
    let limit = srcSize.wrapping_sub(HASHLENGTH as size_t).wrapping_add(1);
    let mut n: size_t = 0;
    n = 0;
    while n < limit {
        let fresh0 = &mut (*((*fp).events)
            .as_mut_ptr()
            .offset(hash2(p.add(n) as *const core::ffi::c_void, hashLog) as isize));
        *fresh0 = (*fresh0).wrapping_add(1);
        n = n.wrapping_add(samplingRate);
    }
    (*fp).nbEvents = ((*fp).nbEvents).wrapping_add(limit / samplingRate);
}
#[inline(always)]
unsafe fn recordFingerprint_generic(
    fp: *mut Fingerprint,
    src: *const core::ffi::c_void,
    srcSize: size_t,
    samplingRate: size_t,
    hashLog: core::ffi::c_uint,
) {
    ptr::write_bytes(
        fp as *mut u8,
        0,
        ::core::mem::size_of::<core::ffi::c_uint>() << hashLog,
    );
    (*fp).nbEvents = 0;
    addEvents_generic(fp, src, srcSize, samplingRate, hashLog);
}
unsafe fn ZSTD_recordFingerprint_1(
    fp: *mut Fingerprint,
    src: *const core::ffi::c_void,
    srcSize: size_t,
) {
    recordFingerprint_generic(fp, src, srcSize, 1, 10);
}
unsafe fn ZSTD_recordFingerprint_5(
    fp: *mut Fingerprint,
    src: *const core::ffi::c_void,
    srcSize: size_t,
) {
    recordFingerprint_generic(fp, src, srcSize, 5, 10);
}
unsafe fn ZSTD_recordFingerprint_11(
    fp: *mut Fingerprint,
    src: *const core::ffi::c_void,
    srcSize: size_t,
) {
    recordFingerprint_generic(fp, src, srcSize, 11, 9);
}
unsafe fn ZSTD_recordFingerprint_43(
    fp: *mut Fingerprint,
    src: *const core::ffi::c_void,
    srcSize: size_t,
) {
    recordFingerprint_generic(fp, src, srcSize, 43, 8);
}
unsafe fn abs64(s64: i64) -> u64 {
    (if s64 < 0 { -s64 } else { s64 }) as u64
}
unsafe fn fpDistance(
    fp1: *const Fingerprint,
    fp2: *const Fingerprint,
    hashLog: core::ffi::c_uint,
) -> u64 {
    let mut distance = 0u64;
    let mut n: size_t = 0;
    n = 0;
    while n < (1) << hashLog {
        distance = distance.wrapping_add(abs64(
            *((*fp1).events).as_ptr().add(n) as i64 * (*fp2).nbEvents as i64
                - *((*fp2).events).as_ptr().add(n) as i64 * (*fp1).nbEvents as i64,
        ));
        n = n.wrapping_add(1);
    }
    distance
}
unsafe fn compareFingerprints(
    ref_0: *const Fingerprint,
    newfp: *const Fingerprint,
    penalty: core::ffi::c_int,
    hashLog: core::ffi::c_uint,
) -> core::ffi::c_int {
    let p50 = (*ref_0).nbEvents * (*newfp).nbEvents;
    let deviation = fpDistance(ref_0, newfp, hashLog);
    let threshold = p50 as u64 * (THRESHOLD_BASE + penalty) as u64 / THRESHOLD_PENALTY_RATE as u64;
    (deviation >= threshold) as core::ffi::c_int
}
unsafe fn mergeEvents(acc: *mut Fingerprint, newfp: *const Fingerprint) {
    let mut n: size_t = 0;
    n = 0;
    while n < HASHTABLESIZE as size_t {
        let fresh1 = &mut (*((*acc).events).as_mut_ptr().add(n));
        *fresh1 = (*fresh1).wrapping_add(*((*newfp).events).as_ptr().add(n));
        n = n.wrapping_add(1);
    }
    (*acc).nbEvents = ((*acc).nbEvents).wrapping_add((*newfp).nbEvents);
}
unsafe fn flushEvents(fpstats: *mut FPStats) {
    let mut n: size_t = 0;
    n = 0;
    while n < HASHTABLESIZE as size_t {
        *((*fpstats).pastEvents.events).as_mut_ptr().add(n) =
            *((*fpstats).newEvents.events).as_mut_ptr().add(n);
        n = n.wrapping_add(1);
    }
    (*fpstats).pastEvents.nbEvents = (*fpstats).newEvents.nbEvents;
    ptr::write_bytes(
        &mut (*fpstats).newEvents as *mut Fingerprint as *mut u8,
        0,
        ::core::mem::size_of::<Fingerprint>(),
    );
}
unsafe fn removeEvents(acc: *mut Fingerprint, slice: *const Fingerprint) {
    let mut n: size_t = 0;
    n = 0;
    while n < HASHTABLESIZE as size_t {
        let fresh2 = &mut (*((*acc).events).as_mut_ptr().add(n));
        *fresh2 = (*fresh2).wrapping_sub(*((*slice).events).as_ptr().add(n));
        n = n.wrapping_add(1);
    }
    (*acc).nbEvents = ((*acc).nbEvents).wrapping_sub((*slice).nbEvents);
}
pub const CHUNKSIZE: core::ffi::c_int = (8) << 10;
unsafe fn ZSTD_splitBlock_byChunks(
    blockStart: *const core::ffi::c_void,
    blockSize: size_t,
    level: core::ffi::c_int,
    workspace: *mut core::ffi::c_void,
    wkspSize: size_t,
) -> size_t {
    static records_fs: [RecordEvents_f; 4] = [
        Some(
            ZSTD_recordFingerprint_43
                as unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> (),
        ),
        Some(
            ZSTD_recordFingerprint_11
                as unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> (),
        ),
        Some(
            ZSTD_recordFingerprint_5
                as unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> (),
        ),
        Some(
            ZSTD_recordFingerprint_1
                as unsafe fn(*mut Fingerprint, *const core::ffi::c_void, size_t) -> (),
        ),
    ];
    static hashParams: [core::ffi::c_uint; 4] = [8, 9, 10, 10];
    let record_f: RecordEvents_f = *records_fs.as_ptr().offset(level as isize);
    let fpstats = workspace as *mut FPStats;
    let p = blockStart as *const core::ffi::c_char;
    let mut penalty = THRESHOLD_PENALTY;
    let mut pos = 0;
    initStats(fpstats);
    record_f.unwrap_unchecked()(
        &mut (*fpstats).pastEvents,
        p as *const core::ffi::c_void,
        CHUNKSIZE as size_t,
    );
    pos = CHUNKSIZE as size_t;
    while pos <= blockSize.wrapping_sub(CHUNKSIZE as size_t) {
        record_f.unwrap_unchecked()(
            &mut (*fpstats).newEvents,
            p.add(pos) as *const core::ffi::c_void,
            CHUNKSIZE as size_t,
        );
        if compareFingerprints(
            &(*fpstats).pastEvents,
            &(*fpstats).newEvents,
            penalty,
            *hashParams.as_ptr().offset(level as isize),
        ) != 0
        {
            return pos;
        } else {
            mergeEvents(&mut (*fpstats).pastEvents, &(*fpstats).newEvents);
            if penalty > 0 {
                penalty -= 1;
            }
        }
        pos = pos.wrapping_add(CHUNKSIZE as size_t);
    }
    blockSize
}
unsafe fn ZSTD_splitBlock_fromBorders(
    blockStart: *const core::ffi::c_void,
    blockSize: size_t,
    workspace: *mut core::ffi::c_void,
    wkspSize: size_t,
) -> size_t {
    let fpstats = workspace as *mut FPStats;
    let middleEvents = (workspace as *mut core::ffi::c_char).offset(
        (512 as core::ffi::c_ulong)
            .wrapping_mul(::core::mem::size_of::<core::ffi::c_uint>() as core::ffi::c_ulong)
            as isize,
    ) as *mut core::ffi::c_void as *mut Fingerprint;
    initStats(fpstats);
    HIST_add(
        ((*fpstats).pastEvents.events).as_mut_ptr(),
        blockStart,
        SEGMENT_SIZE as size_t,
    );
    HIST_add(
        ((*fpstats).newEvents.events).as_mut_ptr(),
        (blockStart as *const core::ffi::c_char)
            .add(blockSize)
            .offset(-(SEGMENT_SIZE as isize)) as *const core::ffi::c_void,
        SEGMENT_SIZE as size_t,
    );
    (*fpstats).newEvents.nbEvents = SEGMENT_SIZE as size_t;
    (*fpstats).pastEvents.nbEvents = (*fpstats).newEvents.nbEvents;
    if compareFingerprints(&(*fpstats).pastEvents, &(*fpstats).newEvents, 0, 8) == 0 {
        return blockSize;
    }
    HIST_add(
        ((*middleEvents).events).as_mut_ptr(),
        (blockStart as *const core::ffi::c_char)
            .add(blockSize / 2)
            .offset(-((SEGMENT_SIZE / 2) as isize)) as *const core::ffi::c_void,
        SEGMENT_SIZE as size_t,
    );
    (*middleEvents).nbEvents = SEGMENT_SIZE as size_t;
    let distFromBegin = fpDistance(&(*fpstats).pastEvents, middleEvents, 8);
    let distFromEnd = fpDistance(&(*fpstats).newEvents, middleEvents, 8);
    let minDistance = (SEGMENT_SIZE * SEGMENT_SIZE / 3) as u64;
    if abs64(distFromBegin as i64 - distFromEnd as i64) < minDistance {
        return (64 * ((1) << 10)) as size_t;
    }
    (if distFromBegin > distFromEnd {
        32 * ((1) << 10)
    } else {
        96 * ((1) << 10)
    }) as size_t
}
pub const SEGMENT_SIZE: core::ffi::c_int = 512;
pub unsafe fn ZSTD_splitBlock(
    blockStart: *const core::ffi::c_void,
    blockSize: size_t,
    level: core::ffi::c_int,
    workspace: *mut core::ffi::c_void,
    wkspSize: size_t,
) -> size_t {
    if level == 0 {
        return ZSTD_splitBlock_fromBorders(blockStart, blockSize, workspace, wkspSize);
    }
    ZSTD_splitBlock_byChunks(blockStart, blockSize, level - 1, workspace, wkspSize)
}