openzl-sys-rs 0.2.0

Low-level Rust bindings to statically linked OpenZL (facebook/openzl). Source downloaded at build time.
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]

include!("bindings.rs");

/// Check if a ZL_Report represents an error
#[inline]
pub fn zl_is_error(report: ZL_Report) -> bool {
    unsafe { report._code != ZL_ErrorCode_ZL_ErrorCode_no_error }
}

/// Extract the size_t value from a successful ZL_Report
#[inline]
pub fn zl_report_value(report: ZL_Report) -> usize {
    unsafe { report._value._value }
}

/// Safe wrapper around ZL_CCtx
pub struct ZlCCtx {
    raw: *mut ZL_CCtx,
}

unsafe impl Send for ZlCCtx {}

impl ZlCCtx {
    pub fn new() -> Option<Self> {
        let raw = unsafe { ZL_CCtx_create() };
        if raw.is_null() {
            None
        } else {
            Some(Self { raw })
        }
    }

    pub fn set_parameter(&mut self, param: ZL_CParam, value: i32) -> Result<(), String> {
        let report = unsafe { ZL_CCtx_setParameter(self.raw, param, value) };
        if zl_is_error(report) {
            Err("ZL_CCtx_setParameter failed".to_string())
        } else {
            Ok(())
        }
    }

    /// Compress src into dst. Returns number of bytes written.
    pub fn compress(&mut self, dst: &mut [u8], src: &[u8]) -> Result<usize, String> {
        let report = unsafe {
            ZL_CCtx_compress(
                self.raw,
                dst.as_mut_ptr() as *mut _,
                dst.len(),
                src.as_ptr() as *const _,
                src.len(),
            )
        };
        if zl_is_error(report) {
            let code = unsafe { report._code };
            Err(format!("ZL_CCtx_compress failed (error code: {})", code))
        } else {
            Ok(zl_report_value(report))
        }
    }

    pub fn as_raw(&self) -> *mut ZL_CCtx {
        self.raw
    }
}

impl Drop for ZlCCtx {
    fn drop(&mut self) {
        unsafe { ZL_CCtx_free(self.raw) };
    }
}

/// Safe wrapper around ZL_DCtx
pub struct ZlDCtx {
    raw: *mut ZL_DCtx,
}

unsafe impl Send for ZlDCtx {}

impl ZlDCtx {
    pub fn new() -> Option<Self> {
        let raw = unsafe { ZL_DCtx_create() };
        if raw.is_null() {
            None
        } else {
            Some(Self { raw })
        }
    }

    /// Decompress src into dst. Returns decompressed size.
    pub fn decompress(&mut self, dst: &mut [u8], src: &[u8]) -> Result<usize, String> {
        let report = unsafe {
            ZL_DCtx_decompress(
                self.raw,
                dst.as_mut_ptr() as *mut _,
                dst.len(),
                src.as_ptr() as *const _,
                src.len(),
            )
        };
        if zl_is_error(report) {
            Err("ZL_DCtx_decompress failed".to_string())
        } else {
            Ok(zl_report_value(report))
        }
    }

    pub fn as_raw(&self) -> *mut ZL_DCtx {
        self.raw
    }
}

impl Drop for ZlDCtx {
    fn drop(&mut self) {
        unsafe { ZL_DCtx_free(self.raw) };
    }
}

/// One-shot decompress (stateless). Returns decompressed size.
pub fn zl_decompress(dst: &mut [u8], src: &[u8]) -> Result<usize, String> {
    let report = unsafe {
        ZL_decompress(
            dst.as_mut_ptr() as *mut _,
            dst.len(),
            src.as_ptr() as *const _,
            src.len(),
        )
    };
    if zl_is_error(report) {
        Err("ZL_decompress failed".to_string())
    } else {
        Ok(zl_report_value(report))
    }
}

/// Get compress bound for given input size
#[inline]
pub fn zl_compress_bound(src_size: usize) -> usize {
    // ZL_COMPRESSBOUND macro: src + frame overhead + per-chunk overhead
    const ZL_MIN_CHUNK_SIZE: usize = 32768;
    const ZL_CHUNK_OVERHEAD_MAX: usize = 16;
    const ZL_FRAME_OVERHEAD_MAX: usize = 64;
    src_size + ZL_FRAME_OVERHEAD_MAX + ((src_size / ZL_MIN_CHUNK_SIZE) + 1) * ZL_CHUNK_OVERHEAD_MAX
}

/// Get decompressed size from compressed frame header
pub fn zl_get_decompressed_size(src: &[u8]) -> Result<usize, String> {
    let report = unsafe { ZL_getDecompressedSize(src.as_ptr() as *const _, src.len()) };
    if zl_is_error(report) {
        Err("ZL_getDecompressedSize failed".to_string())
    } else {
        Ok(zl_report_value(report))
    }
}