Precisely unrolled VarInt reading

This commit is contained in:
Andrew Steinborn
2021-05-30 16:20:28 -04:00
parent 063a208f5f
commit e093c91a26

View File

@@ -91,16 +91,51 @@ public enum ProtocolUtils {
* @return the decoded VarInt, or {@code Integer.MIN_VALUE} if the varint is invalid * @return the decoded VarInt, or {@code Integer.MIN_VALUE} if the varint is invalid
*/ */
public static int readVarIntSafely(ByteBuf buf) { public static int readVarIntSafely(ByteBuf buf) {
int i = 0; // This is pretty messy, but there's two cases we must watch out for: no more bytes left to
int maxRead = Math.min(5, buf.readableBytes()); // read, or we've read more than 5 bytes. It'd be nice if all the checks we had to do could be
for (int j = 0; j < maxRead; j++) { // done in Netty itself, but *shrug*
int k = buf.readByte(); if (!buf.isReadable()) {
i |= (k & 0x7F) << (j * 7); return Integer.MIN_VALUE;
if ((k & 0x80) != 128) { }
return i; int tmp;
} if ((tmp = buf.readByte()) >= 0) {
return tmp;
} else {
if (!buf.isReadable()) {
return Integer.MIN_VALUE;
}
int result = tmp & 0x7f;
if ((tmp = buf.readByte()) >= 0) {
result |= tmp << 7;
} else {
if (!buf.isReadable()) {
return Integer.MIN_VALUE;
}
result |= (tmp & 0x7f) << 7;
if ((tmp = buf.readByte()) >= 0) {
result |= tmp << 14;
} else {
if (!buf.isReadable()) {
return Integer.MIN_VALUE;
}
result |= (tmp & 0x7f) << 14;
if ((tmp = buf.readByte()) >= 0) {
result |= tmp << 21;
} else {
if (!buf.isReadable()) {
return Integer.MIN_VALUE;
}
result |= (tmp & 0x7f) << 21;
if ((tmp = buf.readByte()) >= 0) {
result |= tmp << 28;
} else {
return Integer.MIN_VALUE;
}
}
}
}
return result;
} }
return Integer.MIN_VALUE;
} }
/** /**