optimization: ise varint on field counter for extendable format (it's rare for a struct to have so many fields so smartint will be better).

This commit is contained in:
Sergey Chernov 2023-03-15 09:51:42 +01:00
parent e556d4bc3d
commit 149a0e1850
6 changed files with 23 additions and 10 deletions

View File

@ -22,6 +22,11 @@ interface DataSink {
fun writeBytes(data: ByteArray) { fun writeBytes(data: ByteArray) {
for(d in data) writeByte(d) for(d in data) writeByte(d)
} }
fun writeVarUInt(value: UInt) { Varint.encodeUnsigned(value.toULong())}
fun writeVarInt(value: UInt) { Varint.encodeSigned(value.toLong())}
fun writeSmartUInt(value: UInt) { Smartint.encodeUnsigned(value.toULong())}
fun writeSmartInt(value: UInt) { Smartint.encodeSigned(value.toLong())}
} }
inline fun <reified T:Any>DataSink.writeNumber(value: T) { inline fun <reified T:Any>DataSink.writeNumber(value: T) {

View File

@ -34,6 +34,14 @@ interface DataSource {
fun readFloat() = Float.fromBits(readI32()).toFloat() fun readFloat() = Float.fromBits(readI32()).toFloat()
fun readSmartUInt(): UInt = Smartint.decodeUnsigned(this).toUInt()
fun readSmartInt(): Int = Smartint.decodeSigned(this).toInt()
fun readVarUInt(): UInt = Varint.decodeUnsigned(this).toUInt()
fun readVarInt(): Int = Varint.decodeSigned(this).toInt()
} }
fun ByteArray.toDataSource(): DataSource = fun ByteArray.toDataSource(): DataSource =

View File

@ -59,8 +59,8 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0,val isColl
// CRC-calculating one, and the fields below are CRC protected too: // CRC-calculating one, and the fields below are CRC protected too:
var count = descriptor.elementsCount var count = descriptor.elementsCount
for (a in descriptor.annotations) { for (a in descriptor.annotations) {
if (a is ExtendableFormat) if (a is Extendable)
count = source.readNumber<UInt>().toInt() count = source.readSmartUInt().toInt()
else if (a is Framed) { else if (a is Framed) {
val code = CRC.crc32(descriptor.serialName.encodeToByteArray()) val code = CRC.crc32(descriptor.serialName.encodeToByteArray())
// if we fail to read CRC, it is IO error, so DataSource.EndOfData will be // if we fail to read CRC, it is IO error, so DataSource.EndOfData will be

View File

@ -72,8 +72,8 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
sink.writeU32( sink.writeU32(
CRC.crc32(descriptor.serialName.encodeToByteArray()) CRC.crc32(descriptor.serialName.encodeToByteArray())
) )
} else if (a is ExtendableFormat) { } else if (a is Extendable) {
sink.writeNumber(descriptor.elementsCount.toUInt()) sink.writeSmartUInt(descriptor.elementsCount.toUInt())
} }
} }
return BipackEncoder(sink) return BipackEncoder(sink)

View File

@ -15,7 +15,7 @@ import kotlinx.serialization.SerialInfo
*/ */
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
@SerialInfo @SerialInfo
annotation class ExtendableFormat annotation class Extendable
/** /**
@ -29,7 +29,7 @@ annotation class Framed
/** /**
* Allow to CRC-protect structures (we suppose to use it with classes only). After the * Allow to CRC-protect structures (we suppose to use it with classes only). After the
* data block its CRC32 will be written and checked. It is memory-wise: it calculates CRC * data block its CRC32 will be written and checked. It is memory-wise: it calculates CRC
* on the fly without buffering the data. If used with [Framed] and [ExtendableFormat] the extra * on the fly without buffering the data. If used with [Framed] and [Extendable] the extra
* data is protected too. * data is protected too.
* *
* __Common pitfalls__. When unpacking corrupted data protected this way, the not only [InvalidFrameCRCException] * __Common pitfalls__. When unpacking corrupted data protected this way, the not only [InvalidFrameCRCException]

View File

@ -11,11 +11,11 @@ import kotlin.test.*
data class Foobar1N(val bar: Int, val foo: Int = 117) data class Foobar1N(val bar: Int, val foo: Int = 117)
@Serializable @Serializable
@ExtendableFormat @Extendable
data class Foobar1(val bar: Int, val foo: Int = 117) data class Foobar1(val bar: Int, val foo: Int = 117)
@Serializable @Serializable
@ExtendableFormat @Extendable
@SerialName("bipack.Foobar1") @SerialName("bipack.Foobar1")
data class Foobar2(val bar: Int, val foo: Int, val other: Int = -1) data class Foobar2(val bar: Int, val foo: Int, val other: Int = -1)
@ -30,12 +30,12 @@ data class FoobarF2(val bar: Int, val foo: Int, val other: Int = -1)
@Serializable @Serializable
@Framed @Framed
@ExtendableFormat @Extendable
data class FoobarF3(val bar: Int, val foo: Int, val other: Int = -1) data class FoobarF3(val bar: Int, val foo: Int, val other: Int = -1)
@Serializable @Serializable
@Framed @Framed
@ExtendableFormat @Extendable
@CrcProtected() @CrcProtected()
data class FoobarFP1(val bar: Int, val foo: Int, val other: Int = -1) data class FoobarFP1(val bar: Int, val foo: Int, val other: Int = -1)