steveloughran commented on code in PR #3555:
URL: https://github.com/apache/parquet-java/pull/3555#discussion_r3240973528


##########
parquet-hadoop/src/main/java/org/apache/parquet/hadoop/CodecFactory.java:
##########
@@ -367,4 +418,447 @@ public abstract void decompress(ByteBuffer input, int 
compressedSize, ByteBuffer
 
     public abstract void release();
   }
+
+  // ---- Optimized Snappy compressor/decompressor using direct JNI calls ----
+
+  /**
+   * Compresses using Snappy's byte-array JNI API directly, bypassing the 
Hadoop
+   * stream abstraction. This avoids intermediate direct ByteBuffer copies and
+   * reduces the compression to a single native call per page.
+   */
+  static class SnappyBytesCompressor extends BytesCompressor {
+    private byte[] outputBuffer;
+
+    @Override
+    public BytesInput compress(BytesInput bytes) throws IOException {
+      byte[] input = bytes.toByteArray();
+      int maxLen = Snappy.maxCompressedLength(input.length);
+      if (outputBuffer == null || outputBuffer.length < maxLen) {
+        outputBuffer = new byte[maxLen];
+      }
+      int compressed = Snappy.compress(input, 0, input.length, outputBuffer, 
0);
+      return BytesInput.from(outputBuffer, 0, compressed);
+    }
+
+    @Override
+    public CompressionCodecName getCodecName() {
+      return CompressionCodecName.SNAPPY;
+    }
+
+    @Override
+    public void release() {
+      outputBuffer = null;
+    }
+  }
+
+  /**
+   * Decompresses using Snappy's byte-array JNI API directly.
+   */
+  static class SnappyBytesDecompressor extends BytesDecompressor {
+    @Override
+    public BytesInput decompress(BytesInput bytes, int decompressedSize) 
throws IOException {
+      byte[] input = bytes.toByteArray();
+      byte[] output = new byte[decompressedSize];
+      Snappy.uncompress(input, 0, input.length, output, 0);
+      return BytesInput.from(output);
+    }
+
+    @Override
+    public void decompress(ByteBuffer input, int compressedSize, ByteBuffer 
output, int decompressedSize)
+        throws IOException {
+      byte[] inputBytes = new byte[compressedSize];
+      input.get(inputBytes);
+      byte[] outputBytes = new byte[decompressedSize];
+      Snappy.uncompress(inputBytes, 0, compressedSize, outputBytes, 0);
+      output.put(outputBytes);
+    }
+
+    @Override
+    public void release() {}
+  }
+
+  // ---- Optimized ZSTD compressor/decompressor using zstd-jni streaming API 
directly ----
+
+  /**
+   * Compresses using zstd-jni's {@link ZstdOutputStreamNoFinalizer} directly,
+   * bypassing the Hadoop codec framework ({@code ZstandardCodec}, {@code 
CodecPool},
+   * {@code CompressionOutputStream} wrapper). Uses a configurable {@link 
BufferPool}
+   * (defaulting to {@link RecyclingBufferPool}) for the internal 128KB output 
buffer,
+   * matching the streaming API's natural buffer size. The buffer pool 
strategy is
+   * controlled by the {@code 
parquet.compression.codec.zstd.bufferPool.enabled} config.
+   * This avoids the overhead of Hadoop codec instantiation and compressor 
pool management
+   * while using the same underlying ZSTD streaming path, which is 
well-optimized for all
+   * input sizes including large pages (256KB+).
+   */
+  static class ZstdBytesCompressor extends BytesCompressor {
+    private final int level;
+    private final int workers;
+    private final BufferPool bufferPool;
+    private final ByteArrayOutputStream compressedOutBuffer;
+
+    ZstdBytesCompressor(int level, int workers, int pageSize, BufferPool 
bufferPool) {
+      this.level = level;
+      this.workers = workers;
+      this.bufferPool = bufferPool;
+      this.compressedOutBuffer = new ByteArrayOutputStream(pageSize);
+    }
+
+    @Override
+    public BytesInput compress(BytesInput bytes) throws IOException {
+      compressedOutBuffer.reset();
+      try (ZstdOutputStreamNoFinalizer zos =
+          new ZstdOutputStreamNoFinalizer(compressedOutBuffer, bufferPool, 
level)) {
+        if (workers > 0) {
+          zos.setWorkers(workers);
+        }
+        bytes.writeAllTo(zos);
+      }
+      return BytesInput.from(compressedOutBuffer);
+    }
+
+    @Override
+    public CompressionCodecName getCodecName() {
+      return CompressionCodecName.ZSTD;
+    }
+
+    @Override
+    public void release() {
+      // ByteArrayOutputStream does not hold native resources
+    }
+  }
+
+  /**
+   * Decompresses using zstd-jni's {@link ZstdInputStreamNoFinalizer} directly,
+   * bypassing the Hadoop codec framework. Uses a configurable {@link 
BufferPool}
+   * for internal buffers, matching the streaming decompression path. The 
buffer pool
+   * strategy is controlled by the {@code 
parquet.compression.codec.zstd.bufferPool.enabled}
+   * config. Reads the full decompressed output in a single pass via
+   * {@link InputStream#readNBytes(int)}.
+   */
+  static class ZstdBytesDecompressor extends BytesDecompressor {
+    private final BufferPool bufferPool;
+
+    ZstdBytesDecompressor(BufferPool bufferPool) {
+      this.bufferPool = bufferPool;
+    }
+
+    @Override
+    public BytesInput decompress(BytesInput bytes, int decompressedSize) 
throws IOException {
+      try (ZstdInputStreamNoFinalizer zis = new 
ZstdInputStreamNoFinalizer(bytes.toInputStream(), bufferPool)) {
+        byte[] output = new byte[decompressedSize];
+        int offset = 0;
+        while (offset < decompressedSize) {
+          int read = zis.read(output, offset, decompressedSize - offset);
+          if (read < 0) {
+            throw new IOException(

Review Comment:
   EOFException would be stricter here



##########
parquet-hadoop/src/main/java/org/apache/parquet/hadoop/CodecFactory.java:
##########
@@ -367,4 +418,447 @@ public abstract void decompress(ByteBuffer input, int 
compressedSize, ByteBuffer
 
     public abstract void release();
   }
+
+  // ---- Optimized Snappy compressor/decompressor using direct JNI calls ----
+
+  /**
+   * Compresses using Snappy's byte-array JNI API directly, bypassing the 
Hadoop
+   * stream abstraction. This avoids intermediate direct ByteBuffer copies and
+   * reduces the compression to a single native call per page.
+   */
+  static class SnappyBytesCompressor extends BytesCompressor {
+    private byte[] outputBuffer;
+
+    @Override
+    public BytesInput compress(BytesInput bytes) throws IOException {
+      byte[] input = bytes.toByteArray();
+      int maxLen = Snappy.maxCompressedLength(input.length);
+      if (outputBuffer == null || outputBuffer.length < maxLen) {
+        outputBuffer = new byte[maxLen];
+      }
+      int compressed = Snappy.compress(input, 0, input.length, outputBuffer, 
0);
+      return BytesInput.from(outputBuffer, 0, compressed);
+    }
+
+    @Override
+    public CompressionCodecName getCodecName() {
+      return CompressionCodecName.SNAPPY;
+    }
+
+    @Override
+    public void release() {
+      outputBuffer = null;
+    }
+  }
+
+  /**
+   * Decompresses using Snappy's byte-array JNI API directly.
+   */
+  static class SnappyBytesDecompressor extends BytesDecompressor {
+    @Override
+    public BytesInput decompress(BytesInput bytes, int decompressedSize) 
throws IOException {
+      byte[] input = bytes.toByteArray();
+      byte[] output = new byte[decompressedSize];
+      Snappy.uncompress(input, 0, input.length, output, 0);
+      return BytesInput.from(output);
+    }
+
+    @Override
+    public void decompress(ByteBuffer input, int compressedSize, ByteBuffer 
output, int decompressedSize)
+        throws IOException {
+      byte[] inputBytes = new byte[compressedSize];
+      input.get(inputBytes);
+      byte[] outputBytes = new byte[decompressedSize];
+      Snappy.uncompress(inputBytes, 0, compressedSize, outputBytes, 0);
+      output.put(outputBytes);
+    }
+
+    @Override
+    public void release() {}
+  }
+
+  // ---- Optimized ZSTD compressor/decompressor using zstd-jni streaming API 
directly ----
+
+  /**
+   * Compresses using zstd-jni's {@link ZstdOutputStreamNoFinalizer} directly,
+   * bypassing the Hadoop codec framework ({@code ZstandardCodec}, {@code 
CodecPool},
+   * {@code CompressionOutputStream} wrapper). Uses a configurable {@link 
BufferPool}
+   * (defaulting to {@link RecyclingBufferPool}) for the internal 128KB output 
buffer,
+   * matching the streaming API's natural buffer size. The buffer pool 
strategy is
+   * controlled by the {@code 
parquet.compression.codec.zstd.bufferPool.enabled} config.
+   * This avoids the overhead of Hadoop codec instantiation and compressor 
pool management
+   * while using the same underlying ZSTD streaming path, which is 
well-optimized for all
+   * input sizes including large pages (256KB+).
+   */
+  static class ZstdBytesCompressor extends BytesCompressor {
+    private final int level;
+    private final int workers;
+    private final BufferPool bufferPool;
+    private final ByteArrayOutputStream compressedOutBuffer;
+
+    ZstdBytesCompressor(int level, int workers, int pageSize, BufferPool 
bufferPool) {
+      this.level = level;
+      this.workers = workers;
+      this.bufferPool = bufferPool;
+      this.compressedOutBuffer = new ByteArrayOutputStream(pageSize);
+    }
+
+    @Override
+    public BytesInput compress(BytesInput bytes) throws IOException {
+      compressedOutBuffer.reset();
+      try (ZstdOutputStreamNoFinalizer zos =
+          new ZstdOutputStreamNoFinalizer(compressedOutBuffer, bufferPool, 
level)) {
+        if (workers > 0) {
+          zos.setWorkers(workers);
+        }
+        bytes.writeAllTo(zos);
+      }
+      return BytesInput.from(compressedOutBuffer);
+    }
+
+    @Override
+    public CompressionCodecName getCodecName() {
+      return CompressionCodecName.ZSTD;
+    }
+
+    @Override
+    public void release() {
+      // ByteArrayOutputStream does not hold native resources
+    }
+  }
+
+  /**
+   * Decompresses using zstd-jni's {@link ZstdInputStreamNoFinalizer} directly,
+   * bypassing the Hadoop codec framework. Uses a configurable {@link 
BufferPool}
+   * for internal buffers, matching the streaming decompression path. The 
buffer pool
+   * strategy is controlled by the {@code 
parquet.compression.codec.zstd.bufferPool.enabled}
+   * config. Reads the full decompressed output in a single pass via
+   * {@link InputStream#readNBytes(int)}.
+   */
+  static class ZstdBytesDecompressor extends BytesDecompressor {
+    private final BufferPool bufferPool;
+
+    ZstdBytesDecompressor(BufferPool bufferPool) {
+      this.bufferPool = bufferPool;
+    }
+
+    @Override
+    public BytesInput decompress(BytesInput bytes, int decompressedSize) 
throws IOException {
+      try (ZstdInputStreamNoFinalizer zis = new 
ZstdInputStreamNoFinalizer(bytes.toInputStream(), bufferPool)) {
+        byte[] output = new byte[decompressedSize];
+        int offset = 0;
+        while (offset < decompressedSize) {
+          int read = zis.read(output, offset, decompressedSize - offset);
+          if (read < 0) {
+            throw new IOException(
+                "Unexpected end of ZSTD stream at offset " + offset + " of " + 
decompressedSize);
+          }
+          offset += read;
+        }
+        return BytesInput.from(output);
+      }
+    }
+
+    @Override
+    public void decompress(ByteBuffer input, int compressedSize, ByteBuffer 
output, int decompressedSize)
+        throws IOException {
+      byte[] inputBytes = new byte[compressedSize];
+      input.get(inputBytes);
+      ByteArrayInputStream bais = new ByteArrayInputStream(inputBytes);
+      try (ZstdInputStreamNoFinalizer zis = new 
ZstdInputStreamNoFinalizer(bais, bufferPool)) {
+        byte[] outputBytes = new byte[decompressedSize];
+        int offset = 0;
+        while (offset < decompressedSize) {
+          int read = zis.read(outputBytes, offset, decompressedSize - offset);
+          if (read < 0) {
+            throw new IOException(
+                "Unexpected end of ZSTD stream at offset " + offset + " of " + 
decompressedSize);
+          }
+          offset += read;
+        }
+        output.put(outputBytes);
+      }
+    }
+
+    @Override
+    public void release() {
+      // No persistent resources - streams are closed per call
+    }
+  }
+
+  // ---- Optimized LZ4_RAW compressor/decompressor using airlift LZ4 directly 
----
+
+  /**
+   * Compresses using airlift's LZ4 compressor directly with heap ByteBuffers,
+   * bypassing the Hadoop stream abstraction and NonBlockedCompressor's direct
+   * buffer copies.
+   */
+  static class Lz4RawBytesCompressor extends BytesCompressor {
+    private final Lz4Compressor compressor = new Lz4Compressor();
+    private byte[] outputBuffer;
+
+    @Override
+    public BytesInput compress(BytesInput bytes) throws IOException {
+      byte[] input = bytes.toByteArray();
+      int maxLen = compressor.maxCompressedLength(input.length);
+      if (outputBuffer == null || outputBuffer.length < maxLen) {
+        outputBuffer = new byte[maxLen];
+      }
+      ByteBuffer inputBuf = ByteBuffer.wrap(input);
+      ByteBuffer outputBuf = ByteBuffer.wrap(outputBuffer);
+      compressor.compress(inputBuf, outputBuf);
+      int compressedSize = outputBuf.position();
+      return BytesInput.from(outputBuffer, 0, compressedSize);
+    }
+
+    @Override
+    public CompressionCodecName getCodecName() {
+      return CompressionCodecName.LZ4_RAW;
+    }
+
+    @Override
+    public void release() {
+      outputBuffer = null;
+    }
+  }
+
+  /**
+   * Decompresses using airlift's LZ4 decompressor directly with heap 
ByteBuffers.
+   */
+  static class Lz4RawBytesDecompressor extends BytesDecompressor {
+    private final Lz4Decompressor decompressor = new Lz4Decompressor();
+
+    @Override
+    public BytesInput decompress(BytesInput bytes, int decompressedSize) 
throws IOException {
+      byte[] input = bytes.toByteArray();
+      byte[] output = new byte[decompressedSize];
+      ByteBuffer inputBuf = ByteBuffer.wrap(input);
+      ByteBuffer outputBuf = ByteBuffer.wrap(output);
+      decompressor.decompress(inputBuf, outputBuf);
+      return BytesInput.from(output);
+    }
+
+    @Override
+    public void decompress(ByteBuffer input, int compressedSize, ByteBuffer 
output, int decompressedSize)
+        throws IOException {
+      byte[] inputBytes = new byte[compressedSize];
+      input.get(inputBytes);
+      byte[] outputBytes = new byte[decompressedSize];
+      ByteBuffer inputBuf = ByteBuffer.wrap(inputBytes);
+      ByteBuffer outputBuf = ByteBuffer.wrap(outputBytes);
+      decompressor.decompress(inputBuf, outputBuf);
+      output.put(outputBytes);
+    }
+
+    @Override
+    public void release() {}
+  }
+
+  // ---- Optimized GZIP compressor/decompressor using Deflater/Inflater 
directly ----
+
+  /** GZIP magic number: 0x1f 0x8b. */
+  private static final int GZIP_MAGIC = 0x8b1f;
+
+  /** Minimal 10-byte GZIP header: magic, method=8 (deflate), flags=0, 
mtime=0, xfl=0, os=0. */
+  private static final byte[] GZIP_HEADER = {
+    0x1f,
+    (byte) 0x8b, // magic
+    0x08, // method: deflate
+    0x00, // flags: none
+    0x00,
+    0x00,
+    0x00,
+    0x00, // mtime: not set
+    0x00, // extra flags
+    0x00 // OS: FAT (matches Java's GZIPOutputStream default)
+  };
+
+  /**
+   * Compresses using {@link Deflater} directly with a reusable instance,
+   * bypassing Hadoop's GzipCodec and the stream overhead of
+   * {@link java.util.zip.GZIPOutputStream}. The Deflater is kept across
+   * calls and reset via {@link Deflater#reset()}, avoiding native zlib
+   * state allocation per page. Writes a minimal GZIP header and trailer
+   * (CRC32 + original size) manually.
+   *
+   * <p>Note: this implementation always uses Java's built-in {@link Deflater}
+   * (java.util.zip / JDK zlib). It does <em>not</em> use Hadoop native 
libraries,
+   * so hardware-accelerated compression via Intel ISA-L will not be used even 
if
+   * the native libraries are installed. The overhead reduction from bypassing 
the
+   * Hadoop codec framework typically outweighs the ISA-L advantage for the 
page
+   * sizes used by Parquet.
+   */
+  static class GzipBytesCompressor extends BytesCompressor {

Review Comment:
   it'd be good to verify that the hadoop gzip can decompress this and vice 
versa, as the regression test on this implementation



##########
parquet-hadoop/src/main/java/org/apache/parquet/hadoop/DirectCodecFactory.java:
##########
@@ -76,6 +85,46 @@ class DirectCodecFactory extends CodecFactory implements 
AutoCloseable {
     DIRECT_DECOMPRESSION_CODEC_CLASS = tempClass;
     CREATE_DIRECT_DECOMPRESSOR_METHOD = tempCreateMethod;
     DECOMPRESS_METHOD = tempDecompressMethod;
+
+    // Initialize Brotli JNI bypass via reflection
+    boolean brotliLoaded = false;
+    Method brotliDecompress = null;
+    Method brotliCompress = null;
+    Constructor<?> brotliDecompressorCtor = null;
+    Constructor<?> brotliCompressorCtor = null;
+    Object brotliParam = null;
+    try {
+      // Load native library
+      Class<?> loaderClass = 
Class.forName("org.meteogroup.jbrotli.libloader.BrotliLibraryLoader");
+      loaderClass.getMethod("loadBrotli").invoke(null);
+
+      // BrotliDeCompressor: no-arg ctor + deCompress(ByteBuffer, ByteBuffer) 
-> int
+      Class<?> decompClass = 
Class.forName("org.meteogroup.jbrotli.BrotliDeCompressor");
+      brotliDecompressorCtor = decompClass.getConstructor();
+      brotliDecompress = decompClass.getMethod("deCompress", ByteBuffer.class, 
ByteBuffer.class);

Review Comment:
   I'd recommend using org.apache.parquet.util.DynMethods for this stuff
   * versions of it in different asf projects (iceberg, hadoop...)
   * uses context classloader, which may matter in some deployments
   * easier!



##########
parquet-hadoop/src/main/java/org/apache/parquet/hadoop/CodecFactory.java:
##########
@@ -367,4 +418,447 @@ public abstract void decompress(ByteBuffer input, int 
compressedSize, ByteBuffer
 
     public abstract void release();
   }
+
+  // ---- Optimized Snappy compressor/decompressor using direct JNI calls ----
+
+  /**
+   * Compresses using Snappy's byte-array JNI API directly, bypassing the 
Hadoop
+   * stream abstraction. This avoids intermediate direct ByteBuffer copies and
+   * reduces the compression to a single native call per page.
+   */
+  static class SnappyBytesCompressor extends BytesCompressor {
+    private byte[] outputBuffer;
+
+    @Override
+    public BytesInput compress(BytesInput bytes) throws IOException {
+      byte[] input = bytes.toByteArray();
+      int maxLen = Snappy.maxCompressedLength(input.length);
+      if (outputBuffer == null || outputBuffer.length < maxLen) {
+        outputBuffer = new byte[maxLen];
+      }
+      int compressed = Snappy.compress(input, 0, input.length, outputBuffer, 
0);
+      return BytesInput.from(outputBuffer, 0, compressed);
+    }
+
+    @Override
+    public CompressionCodecName getCodecName() {
+      return CompressionCodecName.SNAPPY;
+    }
+
+    @Override
+    public void release() {
+      outputBuffer = null;
+    }
+  }
+
+  /**
+   * Decompresses using Snappy's byte-array JNI API directly.
+   */
+  static class SnappyBytesDecompressor extends BytesDecompressor {
+    @Override
+    public BytesInput decompress(BytesInput bytes, int decompressedSize) 
throws IOException {
+      byte[] input = bytes.toByteArray();
+      byte[] output = new byte[decompressedSize];
+      Snappy.uncompress(input, 0, input.length, output, 0);
+      return BytesInput.from(output);
+    }
+
+    @Override
+    public void decompress(ByteBuffer input, int compressedSize, ByteBuffer 
output, int decompressedSize)
+        throws IOException {
+      byte[] inputBytes = new byte[compressedSize];
+      input.get(inputBytes);
+      byte[] outputBytes = new byte[decompressedSize];
+      Snappy.uncompress(inputBytes, 0, compressedSize, outputBytes, 0);
+      output.put(outputBytes);
+    }
+
+    @Override
+    public void release() {}
+  }
+
+  // ---- Optimized ZSTD compressor/decompressor using zstd-jni streaming API 
directly ----
+
+  /**
+   * Compresses using zstd-jni's {@link ZstdOutputStreamNoFinalizer} directly,
+   * bypassing the Hadoop codec framework ({@code ZstandardCodec}, {@code 
CodecPool},
+   * {@code CompressionOutputStream} wrapper). Uses a configurable {@link 
BufferPool}
+   * (defaulting to {@link RecyclingBufferPool}) for the internal 128KB output 
buffer,
+   * matching the streaming API's natural buffer size. The buffer pool 
strategy is
+   * controlled by the {@code 
parquet.compression.codec.zstd.bufferPool.enabled} config.
+   * This avoids the overhead of Hadoop codec instantiation and compressor 
pool management
+   * while using the same underlying ZSTD streaming path, which is 
well-optimized for all
+   * input sizes including large pages (256KB+).
+   */
+  static class ZstdBytesCompressor extends BytesCompressor {
+    private final int level;
+    private final int workers;
+    private final BufferPool bufferPool;
+    private final ByteArrayOutputStream compressedOutBuffer;
+
+    ZstdBytesCompressor(int level, int workers, int pageSize, BufferPool 
bufferPool) {
+      this.level = level;
+      this.workers = workers;
+      this.bufferPool = bufferPool;
+      this.compressedOutBuffer = new ByteArrayOutputStream(pageSize);
+    }
+
+    @Override
+    public BytesInput compress(BytesInput bytes) throws IOException {
+      compressedOutBuffer.reset();
+      try (ZstdOutputStreamNoFinalizer zos =
+          new ZstdOutputStreamNoFinalizer(compressedOutBuffer, bufferPool, 
level)) {
+        if (workers > 0) {
+          zos.setWorkers(workers);
+        }
+        bytes.writeAllTo(zos);
+      }
+      return BytesInput.from(compressedOutBuffer);
+    }
+
+    @Override
+    public CompressionCodecName getCodecName() {
+      return CompressionCodecName.ZSTD;
+    }
+
+    @Override
+    public void release() {
+      // ByteArrayOutputStream does not hold native resources
+    }
+  }
+
+  /**
+   * Decompresses using zstd-jni's {@link ZstdInputStreamNoFinalizer} directly,
+   * bypassing the Hadoop codec framework. Uses a configurable {@link 
BufferPool}
+   * for internal buffers, matching the streaming decompression path. The 
buffer pool
+   * strategy is controlled by the {@code 
parquet.compression.codec.zstd.bufferPool.enabled}
+   * config. Reads the full decompressed output in a single pass via
+   * {@link InputStream#readNBytes(int)}.
+   */
+  static class ZstdBytesDecompressor extends BytesDecompressor {
+    private final BufferPool bufferPool;
+
+    ZstdBytesDecompressor(BufferPool bufferPool) {
+      this.bufferPool = bufferPool;
+    }
+
+    @Override
+    public BytesInput decompress(BytesInput bytes, int decompressedSize) 
throws IOException {
+      try (ZstdInputStreamNoFinalizer zis = new 
ZstdInputStreamNoFinalizer(bytes.toInputStream(), bufferPool)) {
+        byte[] output = new byte[decompressedSize];
+        int offset = 0;
+        while (offset < decompressedSize) {
+          int read = zis.read(output, offset, decompressedSize - offset);
+          if (read < 0) {
+            throw new IOException(
+                "Unexpected end of ZSTD stream at offset " + offset + " of " + 
decompressedSize);
+          }
+          offset += read;
+        }
+        return BytesInput.from(output);
+      }
+    }
+
+    @Override
+    public void decompress(ByteBuffer input, int compressedSize, ByteBuffer 
output, int decompressedSize)
+        throws IOException {
+      byte[] inputBytes = new byte[compressedSize];
+      input.get(inputBytes);
+      ByteArrayInputStream bais = new ByteArrayInputStream(inputBytes);
+      try (ZstdInputStreamNoFinalizer zis = new 
ZstdInputStreamNoFinalizer(bais, bufferPool)) {
+        byte[] outputBytes = new byte[decompressedSize];
+        int offset = 0;
+        while (offset < decompressedSize) {
+          int read = zis.read(outputBytes, offset, decompressedSize - offset);
+          if (read < 0) {
+            throw new IOException(

Review Comment:
   EOFException



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to