From d9d4f0a905cdb6624d6c17bc97d36ff7c3807ec7 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Thu, 5 Mar 2026 13:10:07 +0000 Subject: [PATCH] Add safe Rust Zstd decoding option --- Cargo.toml | 4 ++++ src/decoder/image.rs | 2 ++ tests/decode_images.rs | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d1531f7..f4f5223 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ fax34 = { package = "fax", version = "0.2.6", optional = true } flate2 = { version = "1.0.20", optional = true } weezl = { version = "0.1.10", optional = true } zstd = { version = "0.13", optional = true } +ruzstd = { version = "0.8.2", optional = true } zune-jpeg = { version = "0.5.1", optional = true } image-webp = {version = "0.2.4", optional = true } @@ -45,6 +46,9 @@ jpeg = ["dep:zune-jpeg"] lzw = ["dep:weezl"] webp = ["dep:image-webp"] zstd = ["dep:zstd"] +# Fully safe Rust but much slower Zstd decoding. +# When both zstd and safe-rust-zstd are enabled, zstd takes precedence. +safe-rust-zstd = ["dep:ruzstd"] [[bench]] name = "lzw" diff --git a/src/decoder/image.rs b/src/decoder/image.rs index 2a4366f..fb8fcb4 100644 --- a/src/decoder/image.rs +++ b/src/decoder/image.rs @@ -659,6 +659,8 @@ impl Image { )), #[cfg(feature = "zstd")] CompressionMethod::ZSTD => Box::new(zstd::Decoder::new(reader)?), + #[cfg(all(not(feature = "zstd"), feature = "safe-rust-zstd"))] + CompressionMethod::ZSTD => Box::new(ruzstd::decoding::StreamingDecoder::new(reader).unwrap()), // TODO: Error handling CompressionMethod::PackBits => Box::new(PackBitsReader::new(reader, compressed_length)), #[cfg(feature = "deflate")] CompressionMethod::Deflate | CompressionMethod::OldDeflate => { diff --git a/tests/decode_images.rs b/tests/decode_images.rs index 74f9f9f..08314af 100644 --- a/tests/decode_images.rs +++ b/tests/decode_images.rs @@ -569,7 +569,7 @@ fn test_predictor_3_gray_f32() { } #[test] -#[cfg(feature = "zstd")] +#[cfg(any(feature = "zstd", feature = "safe-rust-zstd"))] fn test_zstd_compression() { // gdal_translate -co COMPRESS=ZSTD -co ZSTD_LEVEL=20 int16.tif int16_zstd.tif test_image_sum_i16("int16_zstd.tif", ColorType::Gray(16), 354396);