#89: Add SnappyIOException to distinguish empty input, incompatible format version, etc.
This commit is contained in:
parent
164e51da2e
commit
f0d7f62881
|
@ -38,7 +38,11 @@ public enum SnappyErrorCode {
|
|||
PARSING_ERROR(2),
|
||||
NOT_A_DIRECT_BUFFER(3),
|
||||
OUT_OF_MEMORY(4),
|
||||
FAILED_TO_UNCOMPRESS(5);
|
||||
FAILED_TO_UNCOMPRESS(5),
|
||||
EMPTY_INPUT(6),
|
||||
INCOMPATIBLE_VERSION(7),
|
||||
INVALID_CHUNK_SIZE(8)
|
||||
;
|
||||
|
||||
public final int id;
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package org.xerial.snappy;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Enhanced IOException with SnappyErrorCode
|
||||
*/
|
||||
public class SnappyIOException extends IOException {
|
||||
private final SnappyErrorCode errorCode;
|
||||
|
||||
public SnappyIOException(SnappyErrorCode errorCode, String message) {
|
||||
super(message);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return String.format("[%s] %s", errorCode.name(), super.getMessage());
|
||||
}
|
||||
|
||||
public SnappyErrorCode getErrorCode() { return errorCode; }
|
||||
|
||||
}
|
|
@ -83,6 +83,10 @@ public class SnappyInputStream extends InputStream
|
|||
}
|
||||
|
||||
// Quick test of the header
|
||||
if(readBytes == 0) {
|
||||
// Snappy produces at least 1-byte result. So the empty input is not a valid input
|
||||
throw new SnappyIOException(SnappyErrorCode.EMPTY_INPUT, "Cannot decompress empty stream");
|
||||
}
|
||||
if (readBytes < header.length || header[0] != SnappyCodec.MAGIC_HEADER[0]) {
|
||||
// do the default uncompression
|
||||
readFully(header, readBytes);
|
||||
|
@ -93,8 +97,8 @@ public class SnappyInputStream extends InputStream
|
|||
if (codec.isValidMagicHeader()) {
|
||||
// The input data is compressed by SnappyOutputStream
|
||||
if (codec.version < SnappyCodec.MINIMUM_COMPATIBLE_VERSION) {
|
||||
throw new IOException(String.format(
|
||||
"compressed with imcompatible codec version %d. At least version %d is required",
|
||||
throw new SnappyIOException(SnappyErrorCode.INCOMPATIBLE_VERSION, String.format(
|
||||
"Compressed with an incompatible codec version %d. At least version %d is required",
|
||||
codec.version, SnappyCodec.MINIMUM_COMPATIBLE_VERSION));
|
||||
}
|
||||
}
|
||||
|
@ -351,20 +355,15 @@ public class SnappyInputStream extends InputStream
|
|||
if (readBytes < chunkSize) {
|
||||
throw new IOException("failed to read chunk");
|
||||
}
|
||||
try {
|
||||
int uncompressedLength = Snappy.uncompressedLength(compressed, 0, chunkSize);
|
||||
if (uncompressed == null || uncompressedLength > uncompressed.length) {
|
||||
uncompressed = new byte[uncompressedLength];
|
||||
}
|
||||
int actualUncompressedLength = Snappy.uncompress(compressed, 0, chunkSize, uncompressed, 0);
|
||||
if (uncompressedLength != actualUncompressedLength) {
|
||||
throw new IOException("invalid uncompressed byte size");
|
||||
throw new SnappyIOException(SnappyErrorCode.INVALID_CHUNK_SIZE, String.format("expected %,d bytes, but decompressed chunk has %,d bytes", uncompressedLength, actualUncompressedLength));
|
||||
}
|
||||
uncompressedLimit = actualUncompressedLength;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IOException("failed to uncompress the chunk: " + e.getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -135,11 +135,11 @@ public class SnappyInputStreamTest
|
|||
SnappyInputStream in = new SnappyInputStream(new ByteArrayInputStream(new byte[0]));
|
||||
byte[] uncompressed = readFully(in);
|
||||
assertEquals(0, uncompressed.length);
|
||||
}
|
||||
catch(Exception e) {
|
||||
fail("should not reach here");
|
||||
}
|
||||
|
||||
catch(SnappyIOException e) {
|
||||
assertEquals(SnappyErrorCode.EMPTY_INPUT, e.getErrorCode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue