fixe #2 effective Instant binary representation (truncates to millis though)

This commit is contained in:
sergeych committed 2023-07-21 16:45:27 +01:00
1 parent d0f29ce06f
commit ee20bfdee7
7 files changed
+111 -4

No files matched your search

@@ -0,0 +1,34 @@
package net.sergeych.bintools
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer
import kotlin.reflect.KType
import kotlin.reflect.typeOf
/**
* Experimental interface for packing and unpacking binary formats.
* Initial support intended for BiPack and BOSS to make it fast replaceable.
* Also, JSON text version with binary converter is presented by default.
*/
interface MotherPacker {
fun <T>pack(type: KType, payload: T): ByteArray
fun <T>unpack(type: KType,packed: ByteArray): T
}
inline fun <reified T>MotherPacker.pack(payload: T) = pack(typeOf<T>(), payload)
inline fun <reified T>MotherPacker.unpack(packed: ByteArray) = unpack<T>(typeOf<T>(), packed)
class JsonPacker : MotherPacker {
override fun <T> pack(type: KType, payload: T): ByteArray {
return Json.encodeToString(serializer(type), payload).encodeToByteArray()
}
override fun <T> unpack(type: KType, packed: ByteArray): T {
return Json.decodeFromString<T>(
serializer(type) as KSerializer<T>,
packed.decodeToString()
)
}
}
@@ -1,5 +1,6 @@
package net.sergeych.bipack
import kotlinx.datetime.Instant
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.descriptors.SerialDescriptor
@@ -15,6 +16,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
*/
@Suppress("UNCHECKED_CAST")
class BipackDecoder(
val input: DataSource, var elementsCount: Int = 0, val isCollection: Boolean = false,
val hasFixedSize: Boolean = false,
@@ -64,12 +66,18 @@ class BipackDecoder(
return elementIndex++
}
override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T {
return if( deserializer == Instant.serializer() )
Instant.fromEpochMilliseconds(decodeLong()) as T
else
super.decodeSerializableValue(deserializer)
}
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 })
val source = if (descriptor.annotations.any { it is CrcProtected })
CRC32Source(input)
else
input
@@ -119,6 +127,7 @@ class BipackDecoder(
fun <T> decode(source: DataSource, deserializer: DeserializationStrategy<T>): T =
BipackDecoder(source).decodeSerializableValue(deserializer)
@Suppress("unused")
inline fun <reified T> decode(source: DataSource): T = decode(source, serializer())
inline fun <reified T> decode(source: ByteArray): T =
decode(source.toDataSource(), serializer())
@@ -1,5 +1,6 @@
package net.sergeych.bipack
import kotlinx.datetime.Instant
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.AbstractEncoder
@@ -76,6 +77,11 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
return this
}
override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) {
if (value is Instant) encodeLong(value.toEpochMilliseconds())
else super.encodeSerializableValue(serializer, value)
}
override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder {
// frame protection should start before anything else:
val sink = if (descriptor.annotations.any { it is CrcProtected })
@@ -115,6 +121,7 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
ArrayDataSink().also { encode(serializer, value, it) }.toByteArray()
inline fun <reified T> encode(value: T) = encode(serializer(), value)
@Suppress("unused")
inline fun <reified T> encode(value: T, sink: DataSink) = encode(serializer(), value, sink)
}
@@ -0,0 +1,18 @@
package net.sergeych.bipack
import kotlinx.serialization.KSerializer
import kotlinx.serialization.serializer
import net.sergeych.bintools.MotherPacker
import net.sergeych.bintools.toDataSource
import kotlin.reflect.KType
class MotherBipack : MotherPacker {
override fun <T> pack(type: KType, payload: T): ByteArray {
return BipackEncoder.encode(serializer(type), payload)
}
override fun <T> unpack(type: KType, packed: ByteArray): T {
return BipackDecoder.decode<T>(packed.toDataSource(),
serializer(type) as KSerializer<T>)
}
}