Skip to content

Commit f0d7f62

Browse files
committed
xerial#89: Add SnappyIOException to distinguish empty input, incompatible format version, etc.
1 parent 164e51d commit f0d7f62

4 files changed

Lines changed: 44 additions & 18 deletions

File tree

src/main/java/org/xerial/snappy/SnappyErrorCode.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ public enum SnappyErrorCode {
3838
PARSING_ERROR(2),
3939
NOT_A_DIRECT_BUFFER(3),
4040
OUT_OF_MEMORY(4),
41-
FAILED_TO_UNCOMPRESS(5);
41+
FAILED_TO_UNCOMPRESS(5),
42+
EMPTY_INPUT(6),
43+
INCOMPATIBLE_VERSION(7),
44+
INVALID_CHUNK_SIZE(8)
45+
;
4246

4347
public final int id;
4448

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.xerial.snappy;
2+
3+
import java.io.IOException;
4+
5+
/**
6+
* Enhanced IOException with SnappyErrorCode
7+
*/
8+
public class SnappyIOException extends IOException {
9+
private final SnappyErrorCode errorCode;
10+
11+
public SnappyIOException(SnappyErrorCode errorCode, String message) {
12+
super(message);
13+
this.errorCode = errorCode;
14+
}
15+
16+
@Override
17+
public String getMessage() {
18+
return String.format("[%s] %s", errorCode.name(), super.getMessage());
19+
}
20+
21+
public SnappyErrorCode getErrorCode() { return errorCode; }
22+
23+
}

src/main/java/org/xerial/snappy/SnappyInputStream.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ protected void readHeader() throws IOException {
8383
}
8484

8585
// Quick test of the header
86+
if(readBytes == 0) {
87+
// Snappy produces at least 1-byte result. So the empty input is not a valid input
88+
throw new SnappyIOException(SnappyErrorCode.EMPTY_INPUT, "Cannot decompress empty stream");
89+
}
8690
if (readBytes < header.length || header[0] != SnappyCodec.MAGIC_HEADER[0]) {
8791
// do the default uncompression
8892
readFully(header, readBytes);
@@ -93,8 +97,8 @@ protected void readHeader() throws IOException {
9397
if (codec.isValidMagicHeader()) {
9498
// The input data is compressed by SnappyOutputStream
9599
if (codec.version < SnappyCodec.MINIMUM_COMPATIBLE_VERSION) {
96-
throw new IOException(String.format(
97-
"compressed with imcompatible codec version %d. At least version %d is required",
100+
throw new SnappyIOException(SnappyErrorCode.INCOMPATIBLE_VERSION, String.format(
101+
"Compressed with an incompatible codec version %d. At least version %d is required",
98102
codec.version, SnappyCodec.MINIMUM_COMPATIBLE_VERSION));
99103
}
100104
}
@@ -351,20 +355,15 @@ protected boolean hasNextChunk() throws IOException {
351355
if (readBytes < chunkSize) {
352356
throw new IOException("failed to read chunk");
353357
}
354-
try {
355-
int uncompressedLength = Snappy.uncompressedLength(compressed, 0, chunkSize);
356-
if (uncompressed == null || uncompressedLength > uncompressed.length) {
357-
uncompressed = new byte[uncompressedLength];
358-
}
359-
int actualUncompressedLength = Snappy.uncompress(compressed, 0, chunkSize, uncompressed, 0);
360-
if (uncompressedLength != actualUncompressedLength) {
361-
throw new IOException("invalid uncompressed byte size");
362-
}
363-
uncompressedLimit = actualUncompressedLength;
358+
int uncompressedLength = Snappy.uncompressedLength(compressed, 0, chunkSize);
359+
if (uncompressed == null || uncompressedLength > uncompressed.length) {
360+
uncompressed = new byte[uncompressedLength];
364361
}
365-
catch (IOException e) {
366-
throw new IOException("failed to uncompress the chunk: " + e.getMessage());
362+
int actualUncompressedLength = Snappy.uncompress(compressed, 0, chunkSize, uncompressed, 0);
363+
if (uncompressedLength != actualUncompressedLength) {
364+
throw new SnappyIOException(SnappyErrorCode.INVALID_CHUNK_SIZE, String.format("expected %,d bytes, but decompressed chunk has %,d bytes", uncompressedLength, actualUncompressedLength));
367365
}
366+
uncompressedLimit = actualUncompressedLength;
368367

369368
return true;
370369
}

src/test/java/org/xerial/snappy/SnappyInputStreamTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,11 @@ public void emptyStream() throws Exception {
135135
SnappyInputStream in = new SnappyInputStream(new ByteArrayInputStream(new byte[0]));
136136
byte[] uncompressed = readFully(in);
137137
assertEquals(0, uncompressed.length);
138-
}
139-
catch(Exception e) {
140138
fail("should not reach here");
141139
}
142-
140+
catch(SnappyIOException e) {
141+
assertEquals(SnappyErrorCode.EMPTY_INPUT, e.getErrorCode());
142+
}
143143
}
144144

145145
}

0 commit comments

Comments
 (0)