@Override
  protected void decompressNative(ByteBuffer compressedBuffer, int compressedBufferOffset, int compressedDataSize,
      ByteBuffer decompressedBuffer, int decompressedBufferOffset, int decompressedDataSize)
      throws CompressionException {

    // Zstd requires both buffers type be the same (either both direct memory or both heap), no mixed.
    if (compressedBuffer.isDirect() != decompressedBuffer.isDirect()) {
      throw new IllegalArgumentException(
          "Cannot decompress due to mismatch sourceBuffer type and compressedBuffer buffer type.");
    }

    // Decompress the buffer either as both direct memory buffer or both heap buffers.
    long decompressedSize;
    if (compressedBuffer.isDirect()) {
      decompressedSize =
          Zstd.decompressDirectByteBuffer(decompressedBuffer, decompressedBufferOffset, decompressedDataSize,
              compressedBuffer, compressedBufferOffset, compressedDataSize);
    } else {
      decompressedSize = Zstd.decompressByteArray(decompressedBuffer.array(),
          decompressedBuffer.arrayOffset() + decompressedBufferOffset, decompressedDataSize, compressedBuffer.array(),
          compressedBuffer.arrayOffset() + compressedBufferOffset, compressedDataSize);
    }

    // Check for error.
    if (Zstd.isError(decompressedSize)) {
      throw new CompressionException(String.format("Zstd decompression failed with error code: %d, name: %s. "
              + "compressedBuffer.limit=%d, compressedBufferOffset=%d, compressedDataSize=%d, "
              + "decompressedBuffer.capacity=%d, decompressedBufferOffset=%d, decompressedDataSize=%d", decompressedSize,
          Zstd.getErrorName(decompressedSize), compressedBuffer.limit(), compressedBufferOffset, compressedDataSize,
          decompressedBuffer.capacity(), decompressedBufferOffset, decompressedDataSize));
    }
  }
Invoke the ZStd decompression algorithm given the compressedBuffer and its offset and size.
The original data is written to the sourceDataBuffer at the specified offset and size.
The size of sourceDataBuffer must be at least the original data size.

@param compressedBuffer The compressed buffer.
@param compressedBufferOffset The offset in compressedBuffer where the decompression should start reading.
@param compressedDataSize Size of the compressed buffer returned from compressNative().
@param decompressedBuffer The buffer to store decompression output (the original source data).
@param decompressedBufferOffset Offset where to write the decompressed data.
@param decompressedDataSize Size of the buffer to hold the decompressed data.  It should be size of original data.
ambry-commons/src/main/java/com/github/ambry/compression/ZstdCompression.java