some support for fixed number
This commit is contained in:
parent
5b8df2ff20
commit
86eb5e9d7f
@ -8,7 +8,7 @@ plugins {
|
|||||||
val serialization_version = "1.3.4"
|
val serialization_version = "1.3.4"
|
||||||
|
|
||||||
group = "net.sergeych"
|
group = "net.sergeych"
|
||||||
version = "0.0.1-SNAPSHOT"
|
version = "0.0.2-SNAPSHOT"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -36,6 +36,10 @@ inline fun <reified T:Any>DataSink.writeNumber(value: T) {
|
|||||||
fun DataSink.writeI32(value: Int) {
|
fun DataSink.writeI32(value: Int) {
|
||||||
writeBytes(intToBytes(value))
|
writeBytes(intToBytes(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun DataSink.writeI16(value: Short) {
|
||||||
|
writeBytes(shortToBytes(value))
|
||||||
|
}
|
||||||
fun DataSink.writeU32(value: UInt) {
|
fun DataSink.writeU32(value: UInt) {
|
||||||
writeBytes(uintToBytes(value))
|
writeBytes(uintToBytes(value))
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ interface DataSource {
|
|||||||
|
|
||||||
fun readU32(): UInt = bytesToUInt(readBytes(4))
|
fun readU32(): UInt = bytesToUInt(readBytes(4))
|
||||||
fun readI32(): Int = bytesToInt(readBytes(4))
|
fun readI32(): Int = bytesToInt(readBytes(4))
|
||||||
|
fun readI16(): Short = bytesToShort(readBytes(2))
|
||||||
fun readI64(): Long = bytesToLong(readBytes(8))
|
fun readI64(): Long = bytesToLong(readBytes(8))
|
||||||
|
|
||||||
fun readDouble() = Double.fromBits(readI64())
|
fun readDouble() = Double.fromBits(readI64())
|
||||||
|
@ -20,6 +20,15 @@ fun intToBytes(value: Int): ByteArray {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
fun shortToBytes(value: Short): ByteArray {
|
||||||
|
var l = value.toInt()
|
||||||
|
val result = ByteArray(2)
|
||||||
|
for (i in 1 downTo 0) {
|
||||||
|
result[i] = (l and 0xFF).toByte()
|
||||||
|
l = l shr 8
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
fun uintToBytes(value: UInt): ByteArray {
|
fun uintToBytes(value: UInt): ByteArray {
|
||||||
var l = value
|
var l = value
|
||||||
@ -52,6 +61,15 @@ fun bytesToInt(b: ByteArray): Int {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun bytesToShort(b: ByteArray): Short {
|
||||||
|
var result: Int = 0
|
||||||
|
for (i in 0 until 2) {
|
||||||
|
result = result shl 8
|
||||||
|
result = result or (b[i].toInt() and 0xFF)
|
||||||
|
}
|
||||||
|
return result.toShort()
|
||||||
|
}
|
||||||
|
|
||||||
fun bytesToUInt(b: ByteArray): UInt {
|
fun bytesToUInt(b: ByteArray): UInt {
|
||||||
var result = 0u
|
var result = 0u
|
||||||
for (i in 0 until 4) {
|
for (i in 0 until 4) {
|
||||||
|
@ -15,18 +15,26 @@ import net.sergeych.bintools.*
|
|||||||
* Decode BiPack format. Note that it relies on [DataSource] so can throw [DataSource.EndOfData]
|
* 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
|
* 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,
|
class BipackDecoder(
|
||||||
val hasFixedSize: Boolean = false) : AbstractDecoder() {
|
val input: DataSource, var elementsCount: Int = 0, val isCollection: Boolean = false,
|
||||||
|
val hasFixedSize: Boolean = false,
|
||||||
|
) : AbstractDecoder() {
|
||||||
private var elementIndex = 0
|
private var elementIndex = 0
|
||||||
|
|
||||||
private var nextIsUnsigned = false
|
private var nextIsUnsigned = false
|
||||||
private var fixedSize = -1
|
private var fixedSize = -1
|
||||||
|
private var fixedNumber = false
|
||||||
|
|
||||||
override val serializersModule: SerializersModule = EmptySerializersModule
|
override val serializersModule: SerializersModule = EmptySerializersModule
|
||||||
override fun decodeBoolean(): Boolean = input.readByte().toInt() != 0
|
override fun decodeBoolean(): Boolean = input.readByte().toInt() != 0
|
||||||
override fun decodeByte(): Byte = input.readByte()
|
override fun decodeByte(): Byte = input.readByte()
|
||||||
override fun decodeShort(): Short = if (nextIsUnsigned) input.readNumber<UInt>().toShort() else input.readNumber()
|
override fun decodeShort(): Short =
|
||||||
override fun decodeInt(): Int = if (nextIsUnsigned) input.readNumber<UInt>().toInt() else input.readNumber()
|
if( fixedNumber ) input.readI16()
|
||||||
|
else if (nextIsUnsigned) input.readNumber<UInt>().toShort() else input.readNumber()
|
||||||
|
override fun decodeInt(): Int =
|
||||||
|
if (fixedNumber) input.readI32()
|
||||||
|
else if (nextIsUnsigned) input.readNumber<UInt>().toInt() else input.readNumber()
|
||||||
|
|
||||||
override fun decodeLong(): Long = if (nextIsUnsigned) input.readNumber<ULong>().toLong() else input.readNumber()
|
override fun decodeLong(): Long = if (nextIsUnsigned) input.readNumber<ULong>().toLong() else input.readNumber()
|
||||||
override fun decodeFloat(): Float = input.readFloat()
|
override fun decodeFloat(): Float = input.readFloat()
|
||||||
override fun decodeDouble(): Double = input.readDouble()
|
override fun decodeDouble(): Double = input.readDouble()
|
||||||
@ -48,6 +56,7 @@ class BipackDecoder(val input: DataSource, var elementsCount: Int = 0,val isColl
|
|||||||
when (a) {
|
when (a) {
|
||||||
is Unsigned -> nextIsUnsigned = true
|
is Unsigned -> nextIsUnsigned = true
|
||||||
is FixedSize -> fixedSize = a.size
|
is FixedSize -> fixedSize = a.size
|
||||||
|
is Fixed -> fixedNumber = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return elementIndex++
|
return elementIndex++
|
||||||
|
@ -13,6 +13,7 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
|
|||||||
|
|
||||||
private var nextIsUnsigned = false
|
private var nextIsUnsigned = false
|
||||||
private var fixedSize: Int = -1
|
private var fixedSize: Int = -1
|
||||||
|
private var fixedNumber: Boolean = false
|
||||||
|
|
||||||
override fun encodeElement(descriptor: SerialDescriptor, index: Int): Boolean =
|
override fun encodeElement(descriptor: SerialDescriptor, index: Int): Boolean =
|
||||||
super.encodeElement(descriptor, index).also {
|
super.encodeElement(descriptor, index).also {
|
||||||
@ -21,21 +22,25 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
|
|||||||
when (a) {
|
when (a) {
|
||||||
is Unsigned -> nextIsUnsigned = true
|
is Unsigned -> nextIsUnsigned = true
|
||||||
is FixedSize -> fixedSize = a.size
|
is FixedSize -> fixedSize = a.size
|
||||||
|
is Fixed -> fixedNumber = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// nextIsUnsigned = descriptor.getElementAnnotations(index).any { it is Unsigned }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val serializersModule: SerializersModule = EmptySerializersModule
|
override val serializersModule: SerializersModule = EmptySerializersModule
|
||||||
override fun encodeBoolean(value: Boolean) = output.writeByte(if (value) 1 else 0)
|
override fun encodeBoolean(value: Boolean) = output.writeByte(if (value) 1 else 0)
|
||||||
override fun encodeByte(value: Byte) = output.writeByte(value.toInt())
|
override fun encodeByte(value: Byte) = output.writeByte(value.toInt())
|
||||||
override fun encodeShort(value: Short) = if (nextIsUnsigned)
|
override fun encodeShort(value: Short) =
|
||||||
|
if (fixedNumber) output.writeI16(value)
|
||||||
|
else if (nextIsUnsigned)
|
||||||
output.writeNumber(value.toUInt())
|
output.writeNumber(value.toUInt())
|
||||||
else
|
else
|
||||||
output.writeNumber(value.toInt())
|
output.writeNumber(value.toInt())
|
||||||
|
|
||||||
override fun encodeInt(value: Int) =
|
override fun encodeInt(value: Int) =
|
||||||
if (nextIsUnsigned) output.writeNumber(value.toUInt())
|
if (fixedNumber)
|
||||||
|
output.writeI32(value)
|
||||||
|
else if (nextIsUnsigned) output.writeNumber(value.toUInt())
|
||||||
else output.writeNumber(value)
|
else output.writeNumber(value)
|
||||||
|
|
||||||
fun encodeUInt(value: UInt) = output.writeNumber(value)
|
fun encodeUInt(value: UInt) = output.writeNumber(value)
|
||||||
|
@ -58,6 +58,10 @@ annotation class Unsigned
|
|||||||
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
|
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
|
||||||
annotation class FixedSize(val size: Int)
|
annotation class FixedSize(val size: Int)
|
||||||
|
|
||||||
|
@SerialInfo
|
||||||
|
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
|
||||||
|
annotation class Fixed
|
||||||
|
|
||||||
open class InvalidFrameException(reason: String) : Exception(reason)
|
open class InvalidFrameException(reason: String) : Exception(reason)
|
||||||
class InvalidFrameHeaderException(reason: String = "Frame header does not match") : InvalidFrameException(reason)
|
class InvalidFrameHeaderException(reason: String = "Frame header does not match") : InvalidFrameException(reason)
|
||||||
class InvalidFrameCRCException : InvalidFrameException("Checksum CRC32 failed")
|
class InvalidFrameCRCException : InvalidFrameException("Checksum CRC32 failed")
|
||||||
|
@ -2,6 +2,7 @@ package bipack
|
|||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import net.sergeych.bintools.encodeToHex
|
||||||
import net.sergeych.bintools.toDump
|
import net.sergeych.bintools.toDump
|
||||||
import net.sergeych.bipack.*
|
import net.sergeych.bipack.*
|
||||||
import kotlin.experimental.xor
|
import kotlin.experimental.xor
|
||||||
@ -297,4 +298,28 @@ class BipackEncoderTest {
|
|||||||
assertEquals(x, d.decodeFromBipack())
|
assertEquals(x, d.decodeFromBipack())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FI32(@Fixed val i: Int)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FU32(@Fixed val i: UInt)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FI16(@Fixed val i: Short)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class FU16(@Fixed val i: UShort)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFixedInt() {
|
||||||
|
val a= FI32(127)
|
||||||
|
println(BipackEncoder.encode(a).toDump())
|
||||||
|
assertContentEquals(byteArrayOf(0,0,0,0x7f), BipackEncoder.encode(a))
|
||||||
|
assertEquals("FF FF FF FF", BipackEncoder.encode(FI32(-1)).encodeToHex())
|
||||||
|
assertEquals(-1, BipackEncoder.encode(FI32(-1)).decodeFromBipack<FI32>().i)
|
||||||
|
assertEquals("FF FF FF FF", BipackEncoder.encode(FU32(0xFFFFFFFFu)).encodeToHex())
|
||||||
|
assertEquals("FF 01 02 03", BipackEncoder.encode(FU32(0xFF010203u)).encodeToHex())
|
||||||
|
assertEquals("FF 03", BipackEncoder.encode(FU16(0xFF03u)).encodeToHex())
|
||||||
|
assertEquals(0x7ffeu, BipackEncoder.encode(FU16(0x7ffeu)).decodeFromBipack<FU16>().i)
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user