refactor(cli): make decompression finish policy explicit in Rust
Extract the mixed-format decompression finish status mapping into a pure Rust policy helper and keep the existing callback side effects, diagnostics, and return values in the ABI wrapper. The explicit enum makes the success, pass-through, report, and impossible-status branches auditable and testable without widening the private fileio boundary. Test Plan: ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings; cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check; make -j1; ./tests/rustLibSmoke; make -j1 -C tests test (all shell tests, large streaming tests, native tester, fuzzer phases, and zstream tester passed).
This commit is contained in:
+86
-13
@@ -5218,6 +5218,31 @@ pub unsafe extern "C" fn FIO_rust_decompressFrames(
|
|||||||
/// successful-file finalization. C keeps the diagnostic and accounting
|
/// successful-file finalization. C keeps the diagnostic and accounting
|
||||||
/// callbacks because they touch `DISPLAY*` state and the private `FIO_ctx_t`
|
/// callbacks because they touch `DISPLAY*` state and the private `FIO_ctx_t`
|
||||||
/// layout; Rust owns the result policy and decides which callback is legal.
|
/// layout; Rust owns the result policy and decides which callback is legal.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
enum DecompressFinishAction {
|
||||||
|
Finish,
|
||||||
|
PassThrough,
|
||||||
|
ReportStatus,
|
||||||
|
Invalid,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn classify_decompress_finish_status(status: c_int) -> DecompressFinishAction {
|
||||||
|
match status {
|
||||||
|
FIO_RUST_DECOMPRESS_OK => DecompressFinishAction::Finish,
|
||||||
|
FIO_RUST_DECOMPRESS_PASS_THROUGH => DecompressFinishAction::PassThrough,
|
||||||
|
FIO_RUST_DECOMPRESS_EMPTY_INPUT
|
||||||
|
| FIO_RUST_DECOMPRESS_SHORT_INPUT
|
||||||
|
| FIO_RUST_DECOMPRESS_GZIP_UNSUPPORTED
|
||||||
|
| FIO_RUST_DECOMPRESS_LZMA_UNSUPPORTED
|
||||||
|
| FIO_RUST_DECOMPRESS_LZ4_UNSUPPORTED
|
||||||
|
| FIO_RUST_DECOMPRESS_FRAME_ERROR
|
||||||
|
| FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT
|
||||||
|
| FIO_RUST_DECOMPRESS_PASS_THROUGH_ERROR
|
||||||
|
| FIO_RUST_DECOMPRESS_ZSTD_UNSUPPORTED => DecompressFinishAction::ReportStatus,
|
||||||
|
_ => DecompressFinishAction::Invalid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn FIO_rust_finishDecompressFrames(
|
pub unsafe extern "C" fn FIO_rust_finishDecompressFrames(
|
||||||
status: c_int,
|
status: c_int,
|
||||||
@@ -5229,29 +5254,21 @@ pub unsafe extern "C" fn FIO_rust_finishDecompressFrames(
|
|||||||
assert!(!callbacks.is_null());
|
assert!(!callbacks.is_null());
|
||||||
|
|
||||||
let callbacks = unsafe { &*callbacks };
|
let callbacks = unsafe { &*callbacks };
|
||||||
match status {
|
match classify_decompress_finish_status(status) {
|
||||||
FIO_RUST_DECOMPRESS_OK => {
|
DecompressFinishAction::Finish => {
|
||||||
if let Some(finish) = callbacks.finish {
|
if let Some(finish) = callbacks.finish {
|
||||||
unsafe { finish(callbacks.opaque, src_file_name, decoded_size) };
|
unsafe { finish(callbacks.opaque, src_file_name, decoded_size) };
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
FIO_RUST_DECOMPRESS_PASS_THROUGH => 0,
|
DecompressFinishAction::PassThrough => 0,
|
||||||
FIO_RUST_DECOMPRESS_EMPTY_INPUT
|
DecompressFinishAction::ReportStatus => {
|
||||||
| FIO_RUST_DECOMPRESS_SHORT_INPUT
|
|
||||||
| FIO_RUST_DECOMPRESS_GZIP_UNSUPPORTED
|
|
||||||
| FIO_RUST_DECOMPRESS_LZMA_UNSUPPORTED
|
|
||||||
| FIO_RUST_DECOMPRESS_LZ4_UNSUPPORTED
|
|
||||||
| FIO_RUST_DECOMPRESS_FRAME_ERROR
|
|
||||||
| FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT
|
|
||||||
| FIO_RUST_DECOMPRESS_PASS_THROUGH_ERROR
|
|
||||||
| FIO_RUST_DECOMPRESS_ZSTD_UNSUPPORTED => {
|
|
||||||
if let Some(report_status) = callbacks.report_status {
|
if let Some(report_status) = callbacks.report_status {
|
||||||
unsafe { report_status(callbacks.opaque, status, src_file_name) };
|
unsafe { report_status(callbacks.opaque, status, src_file_name) };
|
||||||
}
|
}
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
_ => {
|
DecompressFinishAction::Invalid => {
|
||||||
unreachable!("unknown Rust decompression status: {status}");
|
unreachable!("unknown Rust decompression status: {status}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9208,6 +9225,62 @@ mod tests {
|
|||||||
state.finished_sizes.push(decoded_size);
|
state.finished_sizes.push(decoded_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classifies_decompression_finish_statuses() {
|
||||||
|
for (status, expected_action) in [
|
||||||
|
(FIO_RUST_DECOMPRESS_OK, DecompressFinishAction::Finish),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_PASS_THROUGH,
|
||||||
|
DecompressFinishAction::PassThrough,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_EMPTY_INPUT,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_SHORT_INPUT,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_GZIP_UNSUPPORTED,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_LZMA_UNSUPPORTED,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_LZ4_UNSUPPORTED,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_FRAME_ERROR,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_UNSUPPORTED_FORMAT,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_PASS_THROUGH_ERROR,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
FIO_RUST_DECOMPRESS_ZSTD_UNSUPPORTED,
|
||||||
|
DecompressFinishAction::ReportStatus,
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
assert_eq!(classify_decompress_finish_status(status), expected_action);
|
||||||
|
}
|
||||||
|
|
||||||
|
for status in [-1, 99] {
|
||||||
|
assert_eq!(
|
||||||
|
classify_decompress_finish_status(status),
|
||||||
|
DecompressFinishAction::Invalid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn maps_decompression_status_and_finishes_only_success() {
|
fn maps_decompression_status_and_finishes_only_success() {
|
||||||
let mut state = DecompressResultState {
|
let mut state = DecompressResultState {
|
||||||
|
|||||||
Reference in New Issue
Block a user