Skip to content
This repository was archived by the owner on Nov 28, 2025. It is now read-only.

Commit 222ce42

Browse files
committed
redo VarInt reading in faster way and add exception when var int too big or empty
1 parent aebff3c commit 222ce42

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

src/main/kotlin/io/github/dockyardmc/events/Event.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ interface Event {
4040
}
4141

4242
operator fun contains(element: Any) = other.contains(element)
43+
44+
// i hate everything about this
45+
// please suggest something better.
4346
}
4447
}
4548

src/main/kotlin/io/github/dockyardmc/extentions/ExtendedByteBuf.kt

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import java.nio.charset.StandardCharsets
2121
import java.util.*
2222

2323
private const val SEGMENT_BITS: Int = 0x7F
24-
private const val CONTINUE_BIT = 0x80
24+
private const val CONTINUE_BIT: Int = 0x80
25+
private const val MAXIMUM_VAR_INT_SIZE = 5
2526

2627
fun <T> ByteBuf.readList(reader: (ByteBuf) -> T): List<T> {
2728
val list = mutableListOf<T>()
@@ -172,17 +173,26 @@ fun <T : Enum<T>> ByteBuf.writeByteEnum(value: T) {
172173
}
173174

174175
fun ByteBuf.readVarInt(): Int {
175-
// https://github.com/jvm-profiling-tools/async-profiler/blob/a38a375dc62b31a8109f3af97366a307abb0fe6f/src/converter/one/jfr/JfrReader.java#L393
176-
var result = 0
177-
var shift = 0
178-
while (true) {
179-
val byte = readByte().toInt()
180-
result = result or ((byte and 0x7f) shl shift)
181-
if (byte >= 0) {
182-
return result
176+
val readable = this.readableBytes()
177+
if (readable == 0) throw DecoderException("Invalid VarInt")
178+
179+
// decode only one byte first as this is the most common size of varints
180+
var current = this.readByte().toInt()
181+
if ((current and 0x80) != 128) {
182+
return current
183+
}
184+
185+
// no point in while loop that has higher overhead instead of for loop with max size of the varint
186+
val maxRead = MAXIMUM_VAR_INT_SIZE.coerceAtMost(readable)
187+
var varInt = current and 0x7F
188+
for (i in 1..<maxRead) {
189+
current = this.readByte().toInt()
190+
varInt = varInt or ((current and 0x7F) shl i * 7)
191+
if ((current and 0x80) != 128) {
192+
return varInt
183193
}
184-
shift += 7
185194
}
195+
throw DecoderException("Invalid VarInt")
186196
}
187197

188198
fun ByteBuf.writeStringArray(list: Collection<String>) {
@@ -234,7 +244,9 @@ fun ByteBuf.writeVarInt(int: Int) {
234244
}
235245

236246
fun ByteBuf.readString() = readString(Short.MAX_VALUE.toInt())
247+
237248
fun ByteBuf.readUtfAndLength() = readUtfAndLength(Short.MAX_VALUE.toInt())
249+
238250
fun ByteBuf.readString(i: Int): String {
239251
val maxSize = i * 3
240252
val size = this.readVarInt()

0 commit comments

Comments
 (0)