diff --git a/gradle.properties b/gradle.properties index 8e4fd10..0870c91 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/src/main/kotlin/ru/dbotthepony/kommons/io/InputStreamUtils.kt b/src/main/kotlin/ru/dbotthepony/kommons/io/InputStreamUtils.kt index 666545f..54ebae7 100644 --- a/src/main/kotlin/ru/dbotthepony/kommons/io/InputStreamUtils.kt +++ b/src/main/kotlin/ru/dbotthepony/kommons/io/InputStreamUtils.kt @@ -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) -} \ No newline at end of file +} + +fun , 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.readMap(keyReader: S.() -> K, valueReader: S.() -> V): Object2ObjectOpenHashMap { + return readMap(keyReader, valueReader, ::Object2ObjectOpenHashMap) +} + +fun S.readKOptional(reader: S.() -> V): KOptional { + if (read() == 0) { + return KOptional.empty() + } else { + return KOptional(reader(this)) + } +} + +fun S.readOptional(reader: S.() -> V): Optional { + if (read() == 0) { + return Optional.empty() + } else { + return Optional.of(reader(this)) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kommons/io/OutputStreamUtils.kt b/src/main/kotlin/ru/dbotthepony/kommons/io/OutputStreamUtils.kt index 75df993..1b7eb66 100644 --- a/src/main/kotlin/ru/dbotthepony/kommons/io/OutputStreamUtils.kt +++ b/src/main/kotlin/ru/dbotthepony/kommons/io/OutputStreamUtils.kt @@ -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.writeMap(map: Map, 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.writeKOptional(value: KOptional, writer: S.(V) -> Unit) { + write(if (value.isPresent) 1 else 0) + + if (value.isPresent) { + writer(this, value.value) + } +} + +fun S.writeOptional(value: Optional, writer: S.(V) -> Unit) { + write(if (value.isPresent) 1 else 0) + + if (value.isPresent) { + writer(this, value.get()) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kommons/io/StreamCodec.kt b/src/main/kotlin/ru/dbotthepony/kommons/io/StreamCodec.kt index bddf2e9..210a1e7 100644 --- a/src/main/kotlin/ru/dbotthepony/kommons/io/StreamCodec.kt +++ b/src/main/kotlin/ru/dbotthepony/kommons/io/StreamCodec.kt @@ -150,6 +150,34 @@ interface StreamCodec { } } } + + class KOptional(val codec: StreamCodec) : StreamCodec> { + override fun read(stream: DataInputStream): ru.dbotthepony.kommons.util.KOptional { + return stream.readKOptional(codec::read) + } + + override fun write(stream: DataOutputStream, value: ru.dbotthepony.kommons.util.KOptional) { + stream.writeKOptional(value, codec::write) + } + + override fun copy(value: ru.dbotthepony.kommons.util.KOptional): ru.dbotthepony.kommons.util.KOptional { + return value.map(codec::copy) + } + } + + class Optional(val codec: StreamCodec) : StreamCodec> { + override fun read(stream: DataInputStream): java.util.Optional { + return stream.readOptional(codec::read) + } + + override fun write(stream: DataOutputStream, value: java.util.Optional) { + stream.writeOptional(value, codec::write) + } + + override fun copy(value: java.util.Optional): java.util.Optional { + 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 > Class.codec() = StreamCodec.Enum(this) fun > KClass.codec() = StreamCodec.Enum(this.java)