From 7c2d446563cf56f3002ad16690b352a6b5d55fbf Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 26 Jul 2023 11:32:48 +0700 Subject: [PATCH] Move stream extensions from stream codecs to friendly streams --- .../mc/otm/core/util/FriendlyStreams.kt | 169 ++++++++++++++++++ .../mc/otm/core/util/StreamCodecs.kt | 168 ----------------- 2 files changed, 169 insertions(+), 168 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/FriendlyStreams.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/FriendlyStreams.kt index e86462576..246401c95 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/FriendlyStreams.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/FriendlyStreams.kt @@ -14,6 +14,7 @@ import net.minecraftforge.registries.ForgeRegistry import java.io.* import java.math.BigDecimal import java.math.BigInteger +import kotlin.math.absoluteValue // But seriously, Mojang, why would you need to derive from ByteBuf directly, when you can implement // your own InputStream and OutputStream, since ByteBuf is meant to be operated on most time like a stream anyway? @@ -158,3 +159,171 @@ fun > S.readCollection(reader: S.() } fun S.readCollection(reader: S.() -> V) = readCollection(reader, ::ArrayList) + +fun OutputStream.writeInt(value: Int) { + if (this is DataOutput) { + writeInt(value) + return + } + + write(value ushr 24) + write(value ushr 16) + write(value ushr 8) + write(value) +} + +fun InputStream.readInt(): Int { + if (this is DataInput) { + return readInt() + } + + return (read() shl 24) or (read() shl 16) or (read() shl 8) or read() +} + +fun OutputStream.writeLong(value: Long) { + if (this is DataOutput) { + writeLong(value) + return + } + + write((value ushr 48).toInt()) + write((value ushr 40).toInt()) + write((value ushr 32).toInt()) + write((value ushr 24).toInt()) + write((value ushr 16).toInt()) + write((value ushr 8).toInt()) + write(value.toInt()) +} + +fun InputStream.readLong(): Long { + if (this is DataInput) { + return readLong() + } + + return (read().toLong() shl 48) or + (read().toLong() shl 40) or + (read().toLong() shl 32) or + (read().toLong() shl 24) or + (read().toLong() shl 16) or + (read().toLong() shl 8) or + read().toLong() +} + +fun OutputStream.writeFloat(value: Float) = writeInt(value.toBits()) +fun InputStream.readFloat() = Float.fromBits(readInt()) +fun OutputStream.writeDouble(value: Double) = writeLong(value.toBits()) +fun InputStream.readDouble() = Double.fromBits(readLong()) + +fun InputStream.readVarIntLE(sizeLimit: NbtAccounter? = null): Int { + sizeLimit?.accountBytes(1L) + val readFirst = read() + + if (readFirst < 0) { + throw NoSuchElementException("Reached end of stream") + } + + if (readFirst and 64 == 0) { + return if (readFirst and 128 != 0) -(readFirst and 63) else readFirst and 63 + } + + var result = 0 + var nextBit = readFirst and 64 + var read = readFirst and 63 + var i = 0 + + while (nextBit != 0) { + result = result or (read shl i) + sizeLimit?.accountBytes(1L) + read = read() + + if (read < 0) { + throw NoSuchElementException("Reached end of stream") + } + + nextBit = read and 128 + read = read and 127 + + if (i == 0) + i = 6 + else + i += 7 + } + + result = result or (read shl i) + return if (readFirst and 128 != 0) -result else result +} + +fun OutputStream.writeVarIntLE(value: Int) { + write((if (value < 0) 128 else 0) or (if (value in -63 .. 63) 0 else 64) or (value.absoluteValue and 63)) + var written = value.absoluteValue ushr 6 + + while (written != 0) { + write((written and 127) or (if (written >= 128) 128 else 0)) + written = written ushr 7 + } +} + +fun InputStream.readVarLongLE(sizeLimit: NbtAccounter? = null): Long { + sizeLimit?.accountBytes(1L) + + val readFirst = read() + + if (readFirst < 0) { + throw NoSuchElementException("Reached end of stream") + } + + if (readFirst and 64 == 0) { + return if (readFirst and 128 != 0) -(readFirst and 63).toLong() else (readFirst and 63).toLong() + } + + var result = 0L + var nextBit = readFirst and 64 + var read = readFirst and 63 + var i = 0 + + while (nextBit != 0) { + result = result or (read shl i).toLong() + sizeLimit?.accountBytes(1L) + read = read() + + if (read < 0) { + throw NoSuchElementException("Reached end of stream") + } + + nextBit = read and 128 + read = read and 127 + + if (i == 0) + i = 6 + else + i += 7 + } + + result = result or (read shl i).toLong() + return if (readFirst and 128 != 0) -result else result +} + +fun OutputStream.writeVarLongLE(value: Long) { + write((if (value < 0L) 128 else 0) or (if (value in -63 .. 63) 0 else 64) or (value.absoluteValue and 63).toInt()) + var written = value.absoluteValue ushr 6 + + while (written != 0L) { + write((written and 127).toInt() or (if (written >= 128) 128 else 0)) + written = written ushr 7 + } +} + +fun InputStream.readBinaryString(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): String { + val size = readVarIntLE() + require(size >= 0) { "Negative payload size: $size" } + sizeLimit.accountBytes(size.toLong()) + val bytes = ByteArray(size) + read(bytes) + return bytes.decodeToString() +} + +fun OutputStream.writeBinaryString(input: String) { + val bytes = input.encodeToByteArray() + writeVarIntLE(bytes.size) + write(bytes) +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/StreamCodecs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/StreamCodecs.kt index 718a4137d..5b15f435d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/StreamCodecs.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/StreamCodecs.kt @@ -197,171 +197,3 @@ class EnumValueCodec>(clazz: Class) : IStreamCodec, Codec< fun > Class.codec() = EnumValueCodec(this) fun > KClass.codec() = EnumValueCodec(this.java) - -fun OutputStream.writeInt(value: Int) { - if (this is DataOutput) { - writeInt(value) - return - } - - write(value ushr 24) - write(value ushr 16) - write(value ushr 8) - write(value) -} - -fun InputStream.readInt(): Int { - if (this is DataInput) { - return readInt() - } - - return (read() shl 24) or (read() shl 16) or (read() shl 8) or read() -} - -fun OutputStream.writeLong(value: Long) { - if (this is DataOutput) { - writeLong(value) - return - } - - write((value ushr 48).toInt()) - write((value ushr 40).toInt()) - write((value ushr 32).toInt()) - write((value ushr 24).toInt()) - write((value ushr 16).toInt()) - write((value ushr 8).toInt()) - write(value.toInt()) -} - -fun InputStream.readLong(): Long { - if (this is DataInput) { - return readLong() - } - - return (read().toLong() shl 48) or - (read().toLong() shl 40) or - (read().toLong() shl 32) or - (read().toLong() shl 24) or - (read().toLong() shl 16) or - (read().toLong() shl 8) or - read().toLong() -} - -fun OutputStream.writeFloat(value: Float) = writeInt(value.toBits()) -fun InputStream.readFloat() = Float.fromBits(readInt()) -fun OutputStream.writeDouble(value: Double) = writeLong(value.toBits()) -fun InputStream.readDouble() = Double.fromBits(readLong()) - -fun InputStream.readVarIntLE(sizeLimit: NbtAccounter? = null): Int { - sizeLimit?.accountBytes(1L) - val readFirst = read() - - if (readFirst < 0) { - throw NoSuchElementException("Reached end of stream") - } - - if (readFirst and 64 == 0) { - return if (readFirst and 128 != 0) -(readFirst and 63) else readFirst and 63 - } - - var result = 0 - var nextBit = readFirst and 64 - var read = readFirst and 63 - var i = 0 - - while (nextBit != 0) { - result = result or (read shl i) - sizeLimit?.accountBytes(1L) - read = read() - - if (read < 0) { - throw NoSuchElementException("Reached end of stream") - } - - nextBit = read and 128 - read = read and 127 - - if (i == 0) - i = 6 - else - i += 7 - } - - result = result or (read shl i) - return if (readFirst and 128 != 0) -result else result -} - -fun OutputStream.writeVarIntLE(value: Int) { - write((if (value < 0) 128 else 0) or (if (value in -63 .. 63) 0 else 64) or (value.absoluteValue and 63)) - var written = value.absoluteValue ushr 6 - - while (written != 0) { - write((written and 127) or (if (written >= 128) 128 else 0)) - written = written ushr 7 - } -} - -fun InputStream.readVarLongLE(sizeLimit: NbtAccounter? = null): Long { - sizeLimit?.accountBytes(1L) - - val readFirst = read() - - if (readFirst < 0) { - throw NoSuchElementException("Reached end of stream") - } - - if (readFirst and 64 == 0) { - return if (readFirst and 128 != 0) -(readFirst and 63).toLong() else (readFirst and 63).toLong() - } - - var result = 0L - var nextBit = readFirst and 64 - var read = readFirst and 63 - var i = 0 - - while (nextBit != 0) { - result = result or (read shl i).toLong() - sizeLimit?.accountBytes(1L) - read = read() - - if (read < 0) { - throw NoSuchElementException("Reached end of stream") - } - - nextBit = read and 128 - read = read and 127 - - if (i == 0) - i = 6 - else - i += 7 - } - - result = result or (read shl i).toLong() - return if (readFirst and 128 != 0) -result else result -} - -fun OutputStream.writeVarLongLE(value: Long) { - write((if (value < 0L) 128 else 0) or (if (value in -63 .. 63) 0 else 64) or (value.absoluteValue and 63).toInt()) - var written = value.absoluteValue ushr 6 - - while (written != 0L) { - write((written and 127).toInt() or (if (written >= 128) 128 else 0)) - written = written ushr 7 - } -} - -fun InputStream.readBinaryString(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): String { - val size = readVarIntLE() - require(size >= 0) { "Negative payload size: $size" } - sizeLimit.accountBytes(size.toLong()) - val bytes = ByteArray(size) - read(bytes) - return bytes.decodeToString() -} - -fun OutputStream.writeBinaryString(input: String) { - val bytes = input.encodeToByteArray() - writeVarIntLE(bytes.size) - write(bytes) -}