BiPack: added @FixedSize for collection serialization

This commit is contained in:
sergeych committed 2023-03-31 06:20:26 +01:00
1 parent bd19570dec
commit 204f73f045
6 files changed
+156 -91

No files matched your search

@@ -15,10 +15,12 @@ import net.sergeych.bintools.*
* Decode BiPack format. Note that it relies on [DataSource] so can throw [DataSource.EndOfData]
* excpetion. Specific frames when used can throw [InvalidFrameException] and its derivatives.e
*/
class BipackDecoder(val input: DataSource, var elementsCount: Int = 0,val isCollection: Boolean = false) : AbstractDecoder() {
class BipackDecoder(val input: DataSource, var elementsCount: Int = 0,val isCollection: Boolean = false,
val hasFixedSize: Boolean = false) : AbstractDecoder() {
private var elementIndex = 0
private var nextIsUnsigned = false
private var fixedSize = -1
override val serializersModule: SerializersModule = EmptySerializersModule
override fun decodeBoolean(): Boolean = input.readByte().toInt() != 0
@@ -41,7 +43,13 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0,val isColl
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
if (elementIndex >= elementsCount) return CompositeDecoder.DECODE_DONE
nextIsUnsigned = descriptor.getElementAnnotations(elementIndex).any { it is Unsigned }
nextIsUnsigned = false
for( a in descriptor.getElementAnnotations(elementIndex)) {
when(a) {
is Unsigned -> nextIsUnsigned = true
is FixedSize -> fixedSize = a.size
}
}
return elementIndex++
}
@@ -57,7 +65,7 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0,val isColl
// Note: we should read from 'source' explicitely as it might ve
// CRC-calculating one, and the fields below are CRC protected too:
var count = descriptor.elementsCount
var count = if( fixedSize >= 0 ) fixedSize else descriptor.elementsCount
for (a in descriptor.annotations) {
if (a is Extendable)
count = source.readVarUInt().toInt()
@@ -71,11 +79,14 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0,val isColl
}
}
// println("bestr ${descriptor.serialName} d/r ${descriptor.elementsCount}/$count")
return BipackDecoder(source, count, isCollection)
return BipackDecoder(source, count, isCollection, fixedSize >= 0)
}
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
return input.readNumber<UInt>().toInt()
return if( hasFixedSize )
elementsCount
else
input.readNumber<UInt>().toInt()
}
override fun endStructure(descriptor: SerialDescriptor) {
@@ -12,12 +12,19 @@ import net.sergeych.bintools.*
class BipackEncoder(val output: DataSink) : AbstractEncoder() {
private var nextIsUnsigned = false
private var fixedSize: Int = -1
override fun encodeElement(descriptor: SerialDescriptor, index: Int): Boolean {
return super.encodeElement(descriptor, index).also {
nextIsUnsigned = descriptor.getElementAnnotations(index).any { it is Unsigned }
override fun encodeElement(descriptor: SerialDescriptor, index: Int): Boolean =
super.encodeElement(descriptor, index).also {
nextIsUnsigned = false
for (a in descriptor.getElementAnnotations(index)) {
when (a) {
is Unsigned -> nextIsUnsigned = true
is FixedSize -> fixedSize = a.size
}
}
// nextIsUnsigned = descriptor.getElementAnnotations(index).any { it is Unsigned }
}
}
override val serializersModule: SerializersModule = EmptySerializersModule
override fun encodeBoolean(value: Boolean) = output.writeByte(if (value) 1 else 0)
@@ -27,12 +34,9 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
else
output.writeNumber(value.toInt())
override fun encodeInt(value: Int) {
if (nextIsUnsigned)
output.writeNumber(value.toUInt())
else
output.writeNumber(value)
}
override fun encodeInt(value: Int) =
if (nextIsUnsigned) output.writeNumber(value.toUInt())
else output.writeNumber(value)
fun encodeUInt(value: UInt) = output.writeNumber(value)
override fun encodeLong(value: Long) = if (nextIsUnsigned)
@@ -56,7 +60,11 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
override fun encodeEnum(enumDescriptor: SerialDescriptor, index: Int) = output.writeNumber(index.toUInt())
override fun beginCollection(descriptor: SerialDescriptor, collectionSize: Int): CompositeEncoder {
encodeUInt(collectionSize.toUInt())
if (fixedSize < 0)
encodeUInt(collectionSize.toUInt())
else if (collectionSize != fixedSize) {
throw IllegalArgumentException("collection size is $collectionSize while fixed size of $fixedSize is required")
}
return this
}
@@ -47,6 +47,10 @@ annotation class CrcProtected
@Target(AnnotationTarget.FIELD,AnnotationTarget.PROPERTY)
annotation class Unsigned
@SerialInfo
@Target(AnnotationTarget.FIELD,AnnotationTarget.PROPERTY)
annotation class FixedSize(val size: Int)
open class InvalidFrameException(reason: String) : Exception(reason)
class InvalidFrameHeaderException(reason: String = "Frame header does not match") : InvalidFrameException(reason)
class InvalidFrameCRCException : InvalidFrameException("Checksum CRC32 failed")