Writing and reading maps, (k)optionals

This commit is contained in:
DBotThePony 2024-02-10 19:35:09 +07:00
parent 31b1278cc2
commit e150738f37
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 120 additions and 2 deletions

View File

@ -4,7 +4,7 @@ kotlin.code.style=official
specifyKotlinAsDependency=false
projectGroup=ru.dbotthepony.kommons
projectVersion=2.1.1
projectVersion=2.1.2
guavaDepVersion=33.0.0
gsonDepVersion=2.8.9

View File

@ -1,7 +1,9 @@
package ru.dbotthepony.kommons.io
import it.unimi.dsi.fastutil.bytes.ByteArrayList
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
import ru.dbotthepony.kommons.math.Decimal
import ru.dbotthepony.kommons.util.KOptional
import java.io.DataInput
import java.io.EOFException
import java.io.IOException
@ -218,4 +220,36 @@ fun InputStream.readDecimal(): Decimal {
val bytes = ByteArray(size)
read(bytes)
return Decimal.fromByteArray(bytes)
}
}
fun <S : InputStream, M : MutableMap<K, V>, K, V> S.readMap(keyReader: S.() -> K, valueReader: S.() -> V, constructor: (Int) -> M): M {
val size = readVarInt()
require(size >= 0) { "Negative payload size: $size" }
val map = constructor(size)
for (i in 0 until size) {
map[keyReader(this)] = valueReader(this)
}
return map
}
fun <S : InputStream, K, V> S.readMap(keyReader: S.() -> K, valueReader: S.() -> V): Object2ObjectOpenHashMap<K, V> {
return readMap(keyReader, valueReader, ::Object2ObjectOpenHashMap)
}
fun <S : InputStream, V> S.readKOptional(reader: S.() -> V): KOptional<V> {
if (read() == 0) {
return KOptional.empty()
} else {
return KOptional(reader(this))
}
}
fun <S : InputStream, V : Any> S.readOptional(reader: S.() -> V): Optional<V> {
if (read() == 0) {
return Optional.empty()
} else {
return Optional.of(reader(this))
}
}

View File

@ -19,6 +19,7 @@ import ru.dbotthepony.kommons.util.IStruct4f
import ru.dbotthepony.kommons.util.IStruct4i
import ru.dbotthepony.kommons.util.IStruct4l
import ru.dbotthepony.kommons.util.IStruct4s
import ru.dbotthepony.kommons.util.KOptional
import java.io.DataOutput
import java.io.OutputStream
import java.io.RandomAccessFile
@ -257,3 +258,28 @@ fun OutputStream.writeDecimal(value: Decimal) {
writeVarInt(bytes.size)
write(bytes)
}
fun <S : OutputStream, K, V> S.writeMap(map: Map<K, V>, keyWriter: S.(K) -> Unit, valueWriter: S.(V) -> Unit) {
writeVarInt(map.size)
for ((k, v) in map.entries) {
keyWriter(this, k)
valueWriter(this, v)
}
}
fun <S : OutputStream, V> S.writeKOptional(value: KOptional<V>, writer: S.(V) -> Unit) {
write(if (value.isPresent) 1 else 0)
if (value.isPresent) {
writer(this, value.value)
}
}
fun <S : OutputStream, V : Any> S.writeOptional(value: Optional<V>, writer: S.(V) -> Unit) {
write(if (value.isPresent) 1 else 0)
if (value.isPresent) {
writer(this, value.get())
}
}

View File

@ -150,6 +150,34 @@ interface StreamCodec<V> {
}
}
}
class KOptional<V>(val codec: StreamCodec<V>) : StreamCodec<ru.dbotthepony.kommons.util.KOptional<V>> {
override fun read(stream: DataInputStream): ru.dbotthepony.kommons.util.KOptional<V> {
return stream.readKOptional(codec::read)
}
override fun write(stream: DataOutputStream, value: ru.dbotthepony.kommons.util.KOptional<V>) {
stream.writeKOptional(value, codec::write)
}
override fun copy(value: ru.dbotthepony.kommons.util.KOptional<V>): ru.dbotthepony.kommons.util.KOptional<V> {
return value.map(codec::copy)
}
}
class Optional<V : Any>(val codec: StreamCodec<V>) : StreamCodec<java.util.Optional<V>> {
override fun read(stream: DataInputStream): java.util.Optional<V> {
return stream.readOptional(codec::read)
}
override fun write(stream: DataOutputStream, value: java.util.Optional<V>) {
stream.writeOptional(value, codec::write)
}
override fun copy(value: java.util.Optional<V>): java.util.Optional<V> {
return value.map(codec::copy)
}
}
}
val NullValueCodec = StreamCodec.Impl({ _ -> null }, { _, _ -> })
@ -168,5 +196,35 @@ val VarLongValueCodec = StreamCodec.Impl(DataInputStream::readSignedVarLong, Dat
val BinaryStringCodec = StreamCodec.Impl(DataInputStream::readBinaryString, DataOutputStream::writeBinaryString)
val DecimalValueCodec = StreamCodec.Impl(DataInputStream::readDecimal, DataOutputStream::writeDecimal)
val OptionalBooleanValueCodec = StreamCodec.Optional(BooleanValueCodec)
val OptionalByteValueCodec = StreamCodec.Optional(ByteValueCodec)
val OptionalShortValueCodec = StreamCodec.Optional(ShortValueCodec)
val OptionalCharValueCodec = StreamCodec.Optional(CharValueCodec)
val OptionalIntValueCodec = StreamCodec.Optional(IntValueCodec)
val OptionalLongValueCodec = StreamCodec.Optional(LongValueCodec)
val OptionalFloatValueCodec = StreamCodec.Optional(FloatValueCodec)
val OptionalDoubleValueCodec = StreamCodec.Optional(DoubleValueCodec)
val OptionalBigDecimalValueCodec = StreamCodec.Optional(BigDecimalValueCodec)
val OptionalUUIDValueCodec = StreamCodec.Optional(UUIDValueCodec)
val OptionalVarIntValueCodec = StreamCodec.Optional(VarIntValueCodec)
val OptionalVarLongValueCodec = StreamCodec.Optional(VarLongValueCodec)
val OptionalBinaryStringCodec = StreamCodec.Optional(BinaryStringCodec)
val OptionalDecimalValueCodec = StreamCodec.Optional(DecimalValueCodec)
val KOptionalBooleanValueCodec = StreamCodec.KOptional(BooleanValueCodec)
val KOptionalByteValueCodec = StreamCodec.KOptional(ByteValueCodec)
val KOptionalShortValueCodec = StreamCodec.KOptional(ShortValueCodec)
val KOptionalCharValueCodec = StreamCodec.KOptional(CharValueCodec)
val KOptionalIntValueCodec = StreamCodec.KOptional(IntValueCodec)
val KOptionalLongValueCodec = StreamCodec.KOptional(LongValueCodec)
val KOptionalFloatValueCodec = StreamCodec.KOptional(FloatValueCodec)
val KOptionalDoubleValueCodec = StreamCodec.KOptional(DoubleValueCodec)
val KOptionalBigDecimalValueCodec = StreamCodec.KOptional(BigDecimalValueCodec)
val KOptionalUUIDValueCodec = StreamCodec.KOptional(UUIDValueCodec)
val KOptionalVarIntValueCodec = StreamCodec.KOptional(VarIntValueCodec)
val KOptionalVarLongValueCodec = StreamCodec.KOptional(VarLongValueCodec)
val KOptionalBinaryStringCodec = StreamCodec.KOptional(BinaryStringCodec)
val KOptionalDecimalValueCodec = StreamCodec.KOptional(DecimalValueCodec)
fun <E : Enum<E>> Class<E>.codec() = StreamCodec.Enum(this)
fun <E : Enum<E>> KClass<E>.codec() = StreamCodec.Enum(this.java)