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) {
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) {

View File

@ -34,6 +34,14 @@ interface DataSource {
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 =

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:
var count = descriptor.elementsCount
for (a in descriptor.annotations) {
if (a is ExtendableFormat)
count = source.readNumber<UInt>().toInt()
if (a is Extendable)
count = source.readSmartUInt().toInt()
else if (a is Framed) {
val code = CRC.crc32(descriptor.serialName.encodeToByteArray())
// 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(
CRC.crc32(descriptor.serialName.encodeToByteArray())
)
} else if (a is ExtendableFormat) {
sink.writeNumber(descriptor.elementsCount.toUInt())
} else if (a is Extendable) {
sink.writeSmartUInt(descriptor.elementsCount.toUInt())
}
}
return BipackEncoder(sink)

View File

@ -15,7 +15,7 @@ import kotlinx.serialization.SerialInfo
*/
@Target(AnnotationTarget.CLASS)
@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
* 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.
*
* __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)
@Serializable
@ExtendableFormat
@Extendable
data class Foobar1(val bar: Int, val foo: Int = 117)
@Serializable
@ExtendableFormat
@Extendable
@SerialName("bipack.Foobar1")
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
@Framed
@ExtendableFormat
@Extendable
data class FoobarF3(val bar: Int, val foo: Int, val other: Int = -1)
@Serializable
@Framed
@ExtendableFormat
@Extendable
@CrcProtected()
data class FoobarFP1(val bar: Int, val foo: Int, val other: Int = -1)