feat(fileio): move buffer helpers to Rust
Route file-I/O input/output buffer construction and the LZ4 block-size mapping through Rust ABI leaves while preserving the existing C helper names and public buffer layouts. Add layout, field, and formula coverage. Test Plan: cargo test --manifest-path rust/cli/Cargo.toml --no-default-features --features cli,compression,decompression,benchmark; cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets --no-default-features --features cli,compression,decompression,benchmark; make -B -C programs -j2 zstd zstd-small zstd-frugal; make -B -C tests -j2 test-cli-tests
This commit is contained in:
+11
-7
@@ -309,6 +309,11 @@ static int FIO_shouldDisplayMultipleFileSummary(FIO_ctx_t const* fCtx)
|
||||
int FIO_rust_checkFilenameCollisions(const char** filenameTable, unsigned nbFiles);
|
||||
unsigned FIO_rust_highbit64(unsigned long long v);
|
||||
unsigned long long FIO_rust_getLargestFileSize(const char** inFileNames, unsigned nbFiles);
|
||||
void FIO_rust_setInBuffer(ZSTD_inBuffer* output, const void* buf, size_t s, size_t pos);
|
||||
void FIO_rust_setOutBuffer(ZSTD_outBuffer* output, void* buf, size_t s, size_t pos);
|
||||
#ifdef ZSTD_LZ4COMPRESS
|
||||
int FIO_rust_LZ4_GetBlockSize_FromBlockId(int id);
|
||||
#endif
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -792,18 +797,14 @@ static int FIO_multiFilesConcatWarning(const FIO_ctx_t* fCtx, FIO_prefs_t* prefs
|
||||
static ZSTD_inBuffer setInBuffer(const void* buf, size_t s, size_t pos)
|
||||
{
|
||||
ZSTD_inBuffer i;
|
||||
i.src = buf;
|
||||
i.size = s;
|
||||
i.pos = pos;
|
||||
FIO_rust_setInBuffer(&i, buf, s, pos);
|
||||
return i;
|
||||
}
|
||||
|
||||
static ZSTD_outBuffer setOutBuffer(void* buf, size_t s, size_t pos)
|
||||
{
|
||||
ZSTD_outBuffer o;
|
||||
o.dst = buf;
|
||||
o.size = s;
|
||||
o.pos = pos;
|
||||
FIO_rust_setOutBuffer(&o, buf, s, pos);
|
||||
return o;
|
||||
}
|
||||
|
||||
@@ -1140,7 +1141,10 @@ FIO_compressLzmaFrame(cRess_t* ress,
|
||||
#define LZ4F_max64KB max64KB
|
||||
#endif
|
||||
|
||||
static int FIO_LZ4_GetBlockSize_FromBlockId (int id) { return (1 << (8 + (2 * id))); }
|
||||
static int FIO_LZ4_GetBlockSize_FromBlockId (int id)
|
||||
{
|
||||
return FIO_rust_LZ4_GetBlockSize_FromBlockId(id);
|
||||
}
|
||||
|
||||
static unsigned long long
|
||||
FIO_compressLz4Frame(cRess_t* ress,
|
||||
|
||||
@@ -20,6 +20,20 @@ const FIO_ZSTD_COMPRESSION: c_int = 0;
|
||||
const FIO_OVERLAP_LOG_NOTSET: c_int = 9999;
|
||||
const FIO_LDM_PARAM_NOTSET: c_int = 9999;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FIO_inBuffer {
|
||||
src: *const c_void,
|
||||
size: usize,
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FIO_outBuffer {
|
||||
dst: *mut c_void,
|
||||
size: usize,
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
#[cfg(target_vendor = "apple")]
|
||||
const ZSTD_SPARSE_DEFAULT: c_int = 0;
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
@@ -517,6 +531,53 @@ pub unsafe extern "C" fn FIO_rust_getLargestFileSize(
|
||||
)
|
||||
}
|
||||
|
||||
/// Fill a C-compatible input buffer through an output pointer.
|
||||
///
|
||||
/// The pointer form avoids relying on a cross-language struct return ABI while
|
||||
/// retaining the public `ZSTD_inBuffer` field order and values.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn FIO_rust_setInBuffer(
|
||||
output: *mut FIO_inBuffer,
|
||||
buf: *const c_void,
|
||||
size: usize,
|
||||
pos: usize,
|
||||
) {
|
||||
unsafe {
|
||||
output.write(FIO_inBuffer {
|
||||
src: buf,
|
||||
size,
|
||||
pos,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill a C-compatible output buffer through an output pointer.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn FIO_rust_setOutBuffer(
|
||||
output: *mut FIO_outBuffer,
|
||||
buf: *mut c_void,
|
||||
size: usize,
|
||||
pos: usize,
|
||||
) {
|
||||
unsafe {
|
||||
output.write(FIO_outBuffer {
|
||||
dst: buf,
|
||||
size,
|
||||
pos,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lz4_block_size_from_block_id(id: c_int) -> c_int {
|
||||
1 << (8 + 2 * id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn FIO_rust_LZ4_GetBlockSize_FromBlockId(id: c_int) -> c_int {
|
||||
lz4_block_size_from_block_id(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn filename_path_separator() -> u8 {
|
||||
if cfg!(windows) {
|
||||
@@ -650,6 +711,76 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buffer_shims_preserve_fields_and_c_layout() {
|
||||
let input_word = size_of::<*const c_void>();
|
||||
let output_word = size_of::<*mut c_void>();
|
||||
|
||||
assert_eq!(offset_of!(FIO_inBuffer, src), 0);
|
||||
assert_eq!(offset_of!(FIO_inBuffer, size), input_word);
|
||||
assert_eq!(
|
||||
offset_of!(FIO_inBuffer, pos),
|
||||
input_word + size_of::<usize>()
|
||||
);
|
||||
assert_eq!(
|
||||
size_of::<FIO_inBuffer>(),
|
||||
input_word + 2 * size_of::<usize>()
|
||||
);
|
||||
assert_eq!(offset_of!(FIO_outBuffer, dst), 0);
|
||||
assert_eq!(offset_of!(FIO_outBuffer, size), output_word);
|
||||
assert_eq!(
|
||||
offset_of!(FIO_outBuffer, pos),
|
||||
output_word + size_of::<usize>()
|
||||
);
|
||||
assert_eq!(
|
||||
size_of::<FIO_outBuffer>(),
|
||||
output_word + 2 * size_of::<usize>()
|
||||
);
|
||||
|
||||
let source = [1u8, 2, 3, 4];
|
||||
let mut destination = [0u8; 8];
|
||||
let mut input = FIO_inBuffer {
|
||||
src: ptr::null(),
|
||||
size: 0,
|
||||
pos: 0,
|
||||
};
|
||||
let mut output = FIO_outBuffer {
|
||||
dst: ptr::null_mut(),
|
||||
size: 0,
|
||||
pos: 0,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
FIO_rust_setInBuffer(
|
||||
&mut input,
|
||||
source.as_ptr().cast::<c_void>(),
|
||||
source.len(),
|
||||
1,
|
||||
);
|
||||
FIO_rust_setOutBuffer(
|
||||
&mut output,
|
||||
destination.as_mut_ptr().cast::<c_void>(),
|
||||
destination.len(),
|
||||
2,
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(input.src, source.as_ptr().cast::<c_void>());
|
||||
assert_eq!(input.size, source.len());
|
||||
assert_eq!(input.pos, 1);
|
||||
assert_eq!(output.dst, destination.as_mut_ptr().cast::<c_void>());
|
||||
assert_eq!(output.size, destination.len());
|
||||
assert_eq!(output.pos, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lz4_block_size_shim_preserves_the_block_id_formula() {
|
||||
assert_eq!(FIO_rust_LZ4_GetBlockSize_FromBlockId(0), 1 << 8);
|
||||
assert_eq!(FIO_rust_LZ4_GetBlockSize_FromBlockId(1), 1 << 10);
|
||||
assert_eq!(FIO_rust_LZ4_GetBlockSize_FromBlockId(3), 1 << 14);
|
||||
assert_eq!(FIO_rust_LZ4_GetBlockSize_FromBlockId(4), 1 << 16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn c_layouts_match_the_headers() {
|
||||
let word = size_of::<usize>();
|
||||
|
||||
Reference in New Issue
Block a user