76 lines
3.1 KiB
Kotlin
76 lines
3.1 KiB
Kotlin
package net.sergeych.bipack
|
|
|
|
import kotlinx.serialization.DeserializationStrategy
|
|
import kotlinx.serialization.ExperimentalSerializationApi
|
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
|
import kotlinx.serialization.encoding.AbstractDecoder
|
|
import kotlinx.serialization.encoding.CompositeDecoder
|
|
import kotlinx.serialization.modules.EmptySerializersModule
|
|
import kotlinx.serialization.modules.SerializersModule
|
|
import kotlinx.serialization.serializer
|
|
import net.sergeych.bintools.CRC
|
|
import net.sergeych.bintools.DataSource
|
|
import net.sergeych.bintools.readNumber
|
|
import net.sergeych.bintools.toDataSource
|
|
|
|
class BipackDecoder(val input: DataSource, var elementsCount: Int = 0) : AbstractDecoder() {
|
|
private var elementIndex = 0
|
|
|
|
override val serializersModule: SerializersModule = EmptySerializersModule
|
|
override fun decodeBoolean(): Boolean = input.readByte().toInt() != 0
|
|
override fun decodeByte(): Byte = input.readByte()
|
|
override fun decodeShort(): Short = input.readNumber()
|
|
override fun decodeInt(): Int = input.readNumber()
|
|
override fun decodeLong(): Long = input.readNumber()
|
|
override fun decodeFloat(): Float = input.readFloat()
|
|
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())
|
|
}
|
|
|
|
override fun decodeString(): String = readBytes().decodeToString()
|
|
override fun decodeEnum(enumDescriptor: SerialDescriptor): Int = input.readNumber<UInt>().toInt()
|
|
|
|
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
|
|
if (elementIndex >= elementsCount) return CompositeDecoder.DECODE_DONE
|
|
return elementIndex++
|
|
}
|
|
|
|
override fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder {
|
|
var count = descriptor.elementsCount
|
|
for( a in descriptor.annotations ) {
|
|
if( a is ExtendableFormat )
|
|
count = input.readNumber<UInt>().toInt()
|
|
else if( a is Framed ) {
|
|
val code = CRC.crc32(descriptor.serialName.encodeToByteArray())
|
|
val actual = input.readU32()
|
|
if( code != actual )
|
|
throw InvalidFrameException()
|
|
}
|
|
}
|
|
return BipackDecoder(input, count)
|
|
}
|
|
|
|
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int =
|
|
input.readNumber<UInt>().toInt().also {
|
|
elementsCount = it
|
|
}
|
|
|
|
override fun decodeNotNullMark(): Boolean = decodeBoolean()
|
|
|
|
@ExperimentalSerializationApi
|
|
override fun decodeNull(): Nothing? = null
|
|
|
|
companion object {
|
|
fun <T> decode(source: DataSource, deserializer: DeserializationStrategy<T>): T =
|
|
BipackDecoder(source).decodeSerializableValue(deserializer)
|
|
|
|
inline fun <reified T> decode(source: DataSource): T = decode(source, serializer())
|
|
inline fun <reified T> decode(source: ByteArray): T =
|
|
decode(source.toDataSource(), serializer())
|
|
}
|
|
}
|