feat(rust): export compression bound from Rust
Move the context-free public ZSTD_compressBound ABI into Rust while leaving the stateful compressor context in C. The Rust implementation preserves the size-width-specific input limit, macro arithmetic, and srcSize_wrong error contract used by C callers. Test Plan: - cargo clippy - cargo clippy --benches - cargo clippy --tests - cargo +nightly fmt - cargo test zstd_compress_api::tests -- --nocapture - cargo test --target i686-unknown-linux-gnu zstd_compress_api::tests - make -B -C lib -j2 libzstd.a - fuzzer -s5346 -i1 --no-big-tests Refs: public ZSTD_COMPRESSBOUND macro in lib/zstd.h
This commit is contained in:
@@ -59,19 +59,9 @@
|
|||||||
/*-*************************************
|
/*-*************************************
|
||||||
* Helper functions
|
* Helper functions
|
||||||
***************************************/
|
***************************************/
|
||||||
/* ZSTD_compressBound()
|
/* ZSTD_compressBound() lives in rust/src/zstd_compress_api.rs. Keep this
|
||||||
* Note that the result from this function is only valid for
|
* translation unit for the context implementation, which still calls the
|
||||||
* the one-pass compression functions.
|
* exported ABI symbol. */
|
||||||
* When employing the streaming mode,
|
|
||||||
* if flushes are frequently altering the size of blocks,
|
|
||||||
* the overhead from block headers can make the compressed data larger
|
|
||||||
* than the return value of ZSTD_compressBound().
|
|
||||||
*/
|
|
||||||
size_t ZSTD_compressBound(size_t srcSize) {
|
|
||||||
size_t const r = ZSTD_COMPRESSBOUND(srcSize);
|
|
||||||
if (r==0) return ERROR(srcSize_wrong);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************
|
/*-*************************************
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ pub mod threading;
|
|||||||
pub mod xxhash;
|
pub mod xxhash;
|
||||||
pub mod zstd_common;
|
pub mod zstd_common;
|
||||||
#[cfg(feature = "compression")]
|
#[cfg(feature = "compression")]
|
||||||
|
pub mod zstd_compress_api;
|
||||||
|
#[cfg(feature = "compression")]
|
||||||
pub mod zstd_compress_literals;
|
pub mod zstd_compress_literals;
|
||||||
#[cfg(feature = "compression")]
|
#[cfg(feature = "compression")]
|
||||||
pub mod zstd_compress_sequences;
|
pub mod zstd_compress_sequences;
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
//! Public, context-free compression API helpers.
|
||||||
|
//!
|
||||||
|
//! The stateful compression context remains in the C translation unit for
|
||||||
|
//! now. These helpers have no context layout dependency, so they can expose
|
||||||
|
//! the public ABI directly from Rust.
|
||||||
|
|
||||||
|
use crate::errors::{ZstdErrorCode, ERROR};
|
||||||
|
|
||||||
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
const ZSTD_MAX_INPUT_SIZE: usize = 0xFF00_FF00_FF00_FF00;
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
const ZSTD_MAX_INPUT_SIZE: usize = 0xFF00_FF00;
|
||||||
|
|
||||||
|
const SMALL_INPUT_THRESHOLD: usize = 128 << 10;
|
||||||
|
|
||||||
|
/// Returns the maximum one-pass compressed size, matching
|
||||||
|
/// `ZSTD_COMPRESSBOUND()` and its public error contract.
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn ZSTD_compressBound(src_size: usize) -> usize {
|
||||||
|
if src_size >= ZSTD_MAX_INPUT_SIZE {
|
||||||
|
return ERROR(ZstdErrorCode::SrcSizeWrong);
|
||||||
|
}
|
||||||
|
|
||||||
|
let margin = if src_size < SMALL_INPUT_THRESHOLD {
|
||||||
|
(SMALL_INPUT_THRESHOLD - src_size) >> 11
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
src_size.wrapping_add(src_size >> 8).wrapping_add(margin)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::errors::ERR_isError;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compress_bound_matches_the_public_macro_edges() {
|
||||||
|
assert_eq!(ZSTD_compressBound(0), 64);
|
||||||
|
assert_eq!(ZSTD_compressBound(1), 64);
|
||||||
|
assert_eq!(ZSTD_compressBound(SMALL_INPUT_THRESHOLD - 1), 131_582);
|
||||||
|
assert_eq!(ZSTD_compressBound(SMALL_INPUT_THRESHOLD), 131_584);
|
||||||
|
assert!(ERR_isError(ZSTD_compressBound(ZSTD_MAX_INPUT_SIZE)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user