fixed bugs with platforms and types. Tests pased
This commit is contained in:
1 parent
e4f2644169
commit
e556d4bc3d
4 files changed
+102
-62
No files matched your search
@@ -1,7 +1,5 @@
|
||||
package net.sergeych.bintools
|
||||
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* data input stream-like abstraction. We need it because
|
||||
* kotlinx serialization is synchronous and there us nothing
|
||||
@@ -21,11 +19,12 @@ interface DataSource {
|
||||
fun readUByte() = readByte().toUByte()
|
||||
|
||||
@Suppress("unused")
|
||||
fun readBytes(size: Int): ByteArray =
|
||||
ByteArray(size).also { a ->
|
||||
fun readBytes(size: Int): ByteArray {
|
||||
return ByteArray(size).also { a ->
|
||||
for (i in 0 until size)
|
||||
a[i] = readByte()
|
||||
}
|
||||
}
|
||||
|
||||
fun readU32(): UInt = bytesToUInt(readBytes(4))
|
||||
fun readI32(): Int = bytesToInt(readBytes(4))
|
||||
@@ -33,7 +32,7 @@ interface DataSource {
|
||||
|
||||
fun readDouble() = Double.fromBits(readI64())
|
||||
|
||||
fun readFloat() = Float.fromBits(readI32())
|
||||
fun readFloat() = Float.fromBits(readI32()).toFloat()
|
||||
|
||||
}
|
||||
|
||||
@@ -45,11 +44,11 @@ fun ByteArray.toDataSource(): DataSource =
|
||||
override fun readByte(): Byte =
|
||||
if (position < size) this@toDataSource[position++]
|
||||
else throw DataSource.EndOfData()
|
||||
|
||||
override fun toString(): String {
|
||||
return "ASrc[$position]: ${encodeToHex()}"
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> DataSource.readNumber(): T = when (typeOf<T>()) {
|
||||
typeOf<Double>() -> readDouble() as T
|
||||
typeOf<Float>() -> readFloat() as T
|
||||
else -> Smartint.decode(this)
|
||||
}
|
||||
inline fun <reified T : Any> DataSource.readNumber(): T = Smartint.decode(this) as T
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.sergeych.bipack
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.descriptors.StructureKind
|
||||
import kotlinx.serialization.encoding.AbstractDecoder
|
||||
import kotlinx.serialization.encoding.CompositeDecoder
|
||||
import kotlinx.serialization.modules.EmptySerializersModule
|
||||
@@ -14,7 +15,7 @@ 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) : AbstractDecoder() {
|
||||
class BipackDecoder(val input: DataSource, var elementsCount: Int = 0,val isCollection: Boolean = false) : AbstractDecoder() {
|
||||
private var elementIndex = 0
|
||||
|
||||
private var nextIsUnsigned = false
|
||||
@@ -29,6 +30,7 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0) : Abstrac
|
||||
override fun decodeDouble(): Double = input.readDouble()
|
||||
override fun decodeChar(): Char = Char(input.readNumber<UInt>().toInt())
|
||||
|
||||
|
||||
fun readBytes(): ByteArray {
|
||||
val length = input.readNumber<UInt>()
|
||||
return input.readBytes(length.toInt())
|
||||
@@ -43,7 +45,11 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0) : Abstrac
|
||||
return elementIndex++
|
||||
}
|
||||
|
||||
override fun decodeSequentially(): Boolean = isCollection
|
||||
|
||||
override fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder {
|
||||
val isCollection = descriptor.kind == StructureKind.LIST || descriptor.kind == StructureKind.MAP
|
||||
|
||||
var source = if (descriptor.annotations.any { it is CrcProtected })
|
||||
CRC32Source(input)
|
||||
else
|
||||
@@ -64,11 +70,16 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0) : Abstrac
|
||||
throw InvalidFrameHeaderException()
|
||||
}
|
||||
}
|
||||
return BipackDecoder(source, count)
|
||||
// println("bestr ${descriptor.serialName} d/r ${descriptor.elementsCount}/$count")
|
||||
return BipackDecoder(source, count, isCollection)
|
||||
}
|
||||
|
||||
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
|
||||
return input.readNumber<UInt>().toInt()
|
||||
}
|
||||
|
||||
override fun endStructure(descriptor: SerialDescriptor) {
|
||||
if (input is CRC32Source) {
|
||||
if (input is CRC32Source && descriptor.annotations.any { it is CrcProtected }) {
|
||||
val actual = input.crc
|
||||
val expected = input.readU32()
|
||||
if (actual != expected)
|
||||
@@ -77,12 +88,6 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0) : Abstrac
|
||||
super.endStructure(descriptor)
|
||||
}
|
||||
|
||||
override fun decodeSequentially(): Boolean = true
|
||||
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int =
|
||||
input.readNumber<UInt>().toInt().also {
|
||||
elementsCount = it
|
||||
}
|
||||
|
||||
override fun decodeNotNullMark(): Boolean = decodeBoolean()
|
||||
|
||||
@ExperimentalSerializationApi
|
||||
@@ -98,4 +103,4 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0) : Abstrac
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T>ByteArray.decodeFromBipack() = BipackDecoder.decode<T>(this)
|
||||
inline fun <reified T> ByteArray.decodeFromBipack() = BipackDecoder.decode<T>(this)
|
||||
@@ -9,10 +9,7 @@ import kotlinx.serialization.modules.SerializersModule
|
||||
import kotlinx.serialization.serializer
|
||||
import net.sergeych.bintools.*
|
||||
|
||||
class BipackEncoder(var output: DataSink) : AbstractEncoder() {
|
||||
|
||||
// used when CRC calculation on the fly
|
||||
private var crcSink: CRC32Sink? = null
|
||||
class BipackEncoder(val output: DataSink) : AbstractEncoder() {
|
||||
|
||||
private var nextIsUnsigned = false
|
||||
|
||||
@@ -21,19 +18,15 @@ class BipackEncoder(var output: DataSink) : AbstractEncoder() {
|
||||
nextIsUnsigned = descriptor.getElementAnnotations(index).any { it is Unsigned }
|
||||
}
|
||||
}
|
||||
// fun isUnsigned(): Boolean {
|
||||
//
|
||||
// return
|
||||
// }
|
||||
|
||||
|
||||
override val serializersModule: SerializersModule = EmptySerializersModule
|
||||
override fun encodeBoolean(value: Boolean) = output.writeByte(if (value) 1 else 0)
|
||||
override fun encodeByte(value: Byte) = output.writeByte(value.toInt())
|
||||
override fun encodeShort(value: Short) = if( nextIsUnsigned )
|
||||
override fun encodeShort(value: Short) = if (nextIsUnsigned)
|
||||
output.writeNumber(value.toUInt())
|
||||
else
|
||||
output.writeNumber(value.toInt())
|
||||
|
||||
override fun encodeInt(value: Int) {
|
||||
if (nextIsUnsigned)
|
||||
output.writeNumber(value.toUInt())
|
||||
@@ -42,10 +35,11 @@ class BipackEncoder(var output: DataSink) : AbstractEncoder() {
|
||||
}
|
||||
|
||||
fun encodeUInt(value: UInt) = output.writeNumber(value)
|
||||
override fun encodeLong(value: Long) = if( nextIsUnsigned )
|
||||
override fun encodeLong(value: Long) = if (nextIsUnsigned)
|
||||
output.writeNumber(value.toULong())
|
||||
else
|
||||
output.writeNumber(value)
|
||||
|
||||
override fun encodeFloat(value: Float) = output.writeFloat(value)
|
||||
override fun encodeDouble(value: Double) = output.writeDouble(value)
|
||||
override fun encodeChar(value: Char) = output.writeNumber(value.code.toUInt())
|
||||
@@ -68,29 +62,26 @@ class BipackEncoder(var output: DataSink) : AbstractEncoder() {
|
||||
|
||||
override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder {
|
||||
// frame protection should start before anything else:
|
||||
if (descriptor.annotations.any { it is CrcProtected }) {
|
||||
crcSink = CRC32Sink(output).also {
|
||||
output = it
|
||||
}
|
||||
}
|
||||
// now it is safe to process anything else
|
||||
val sink = if (descriptor.annotations.any { it is CrcProtected })
|
||||
CRC32Sink(output)
|
||||
else
|
||||
output
|
||||
// now it is safe to process anything else using `sink`. not the output!
|
||||
for (a in descriptor.annotations) {
|
||||
if (a is Framed) {
|
||||
output.writeU32(
|
||||
sink.writeU32(
|
||||
CRC.crc32(descriptor.serialName.encodeToByteArray())
|
||||
)
|
||||
} else if (a is ExtendableFormat) {
|
||||
encodeUInt(descriptor.elementsCount.toUInt())
|
||||
sink.writeNumber(descriptor.elementsCount.toUInt())
|
||||
}
|
||||
}
|
||||
return super.beginStructure(descriptor)
|
||||
return BipackEncoder(sink)
|
||||
}
|
||||
|
||||
override fun endStructure(descriptor: SerialDescriptor) {
|
||||
crcSink?.let {
|
||||
output = it.sink
|
||||
crcSink = null
|
||||
output.writeU32(it.crc)
|
||||
if (output is CRC32Sink && descriptor.annotations.any { it is CrcProtected }) {
|
||||
output.writeU32(output.crc)
|
||||
}
|
||||
super.endStructure(descriptor)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user